* [PATCH 01/17] drm/amd/display: enable shaper when programming 3DLUT
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 02/17] drm/amd/display: log MCM shaper and 3D LUT mode in the DTN log Roman.Li
` (16 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen
From: Harry Wentland <harry.wentland@amd.com>
The plane-XR30-XR30-3dlut_17_12_rgb kms_colorop test fails on DCN 4.x.
We need to make sure we set shaper_enable to enable the shaper block,
otherwise the 3DLUT block will stay inactive.
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index eea7e7dcfa30..56d5b9cc8385 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1836,6 +1836,7 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
tf->tf = TRANSFER_FUNCTION_LINEAR;
tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
ret = __set_output_tf_32(tf, NULL, 0, false);
+ dc_plane_state->cm.flags.bits.shaper_enable = 1;
}
} else {
dc_plane_state->cm.flags.bits.lut3d_enable = 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 02/17] drm/amd/display: log MCM shaper and 3D LUT mode in the DTN log
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
2026-10-02 19:32 ` [PATCH 01/17] drm/amd/display: enable shaper when programming 3DLUT Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 03/17] drm/amd/display: only reprogram DRR when v_total values change Roman.Li
` (15 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen
From: Harry Wentland <harry.wentland@amd.com>
On DCN4 the per-plane MCM shaper and 3D LUT state wasn't visible in the
DTN log: dcn401 wired read_mpcc_state to mpc1_read_mpcc_state, which only
reads the base MPCC blend registers, and the MPCC section didn't print the
LUT fields even where they were populated.
Add mpc401_read_mpcc_state to also read MPCC_MCM_3DLUT_MODE (mode current
and size) and MPCC_MCM_SHAPER_CONTROL (mode current), and print SHAPER,
3DLUT and 3DLUT_SIZE columns in the MPCC section. Mode is 0 bypass, 1
RAM_A, 2 RAM_B; 3DLUT_SIZE is 0 for 17x17x17 and 1 for 9x9x9.
Assisted-by: Copilot:claude-opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
.../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 6 +++---
.../drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c | 18 +++++++++++++++++-
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index 884319b22cc1..33f7ab4c6c15 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -542,16 +542,16 @@ static void dcn10_log_color_state(struct dc *dc,
dc->caps.color.dpp.ogam_ram,
dc->caps.color.dpp.ocsc);
- DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE\n");
+ DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE SHAPER 3DLUT 3DLUT_SIZE\n");
for (i = 0; i < pool->mpcc_count; i++) {
struct mpcc_state s = {0};
pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
if (s.opp_id != 0xf)
- DTN_INFO("[%2d]: %2xh %2xh %6xh %4d %10d %7d %12d %4d\n",
+ DTN_INFO("[%2d]: %2xh %2xh %6xh %4d %10d %7d %12d %4d %6d %5d %10d\n",
i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
- s.idle);
+ s.idle, s.shaper_lut_mode, s.lut3d_mode, s.lut3d_size);
}
DTN_INFO("\n");
DTN_INFO("MPC Color Caps: gamut_remap:%d, 3dlut:%d, ogam_ram:%d, ocsc:%d\n\n",
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
index e59454090691..5f5c27eb1d64 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
@@ -627,8 +627,24 @@ void mpc401_get_lut_mode(struct mpc *mpc,
}
}
+static void mpc401_read_mpcc_state(
+ struct mpc *mpc,
+ int mpcc_inst,
+ struct mpcc_state *s)
+{
+ struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
+
+ mpc1_read_mpcc_state(mpc, mpcc_inst, s);
+
+ REG_GET_2(MPCC_MCM_3DLUT_MODE[mpcc_inst],
+ MPCC_MCM_3DLUT_MODE_CURRENT, &s->lut3d_mode,
+ MPCC_MCM_3DLUT_SIZE, &s->lut3d_size);
+ REG_GET(MPCC_MCM_SHAPER_CONTROL[mpcc_inst],
+ MPCC_MCM_SHAPER_MODE_CURRENT, &s->shaper_lut_mode);
+}
+
static const struct mpc_funcs dcn401_mpc_funcs = {
- .read_mpcc_state = mpc1_read_mpcc_state,
+ .read_mpcc_state = mpc401_read_mpcc_state,
.insert_plane = mpc1_insert_plane,
.remove_mpcc = mpc1_remove_mpcc,
.mpc_init = mpc32_mpc_init,
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 03/17] drm/amd/display: only reprogram DRR when v_total values change
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
2026-10-02 19:32 ` [PATCH 01/17] drm/amd/display: enable shaper when programming 3DLUT Roman.Li
2026-10-02 19:32 ` [PATCH 02/17] drm/amd/display: log MCM shaper and 3D LUT mode in the DTN log Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 04/17] drm/amd/display: Add HDMI RR and SCDC skips Roman.Li
` (14 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Aric Cyr, Josip Pavic
From: Aric Cyr <Aric.Cyr@amd.com>
[Why]
dc_stream_adjust_vmin_vmax() programmed the OTG on every call. FreeSync
BTR calls it once per vblank, so identical v_total values were rewritten
every frame, each one paying dc_exit_ips_for_hw_access() and, when FAMS
is enabled, a blocking DMUB round trip from setup_manual_trigger().
[How]
Return early when timing_adjust_pending is clear and every v_total field
already matches the request, so hardware is only touched when the values
change. stream->adjust is still updated on every path that continues, so
a later commit programs the requested values.
timing_adjust_pending is the existing "stream->adjust has not reached
hardware" marker, so keep it accurate wherever hardware is left
untouched: set_drr_and_clear_adjust_pending() now sets it when called
with null params, which resets DRR in the OTG during pipe back-end
teardown, and the max_v_total overflow path only clears it when
set_long_vtotal() runs.
Reviewed-by: Josip Pavic <josip.pavic@amd.com>
Signed-off-by: Aric Cyr <Aric.Cyr@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/core/dc.c | 24 +++++++++++++++----
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 3 ++-
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 17db12fe8022..254c2a9c1b04 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1342,6 +1342,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
struct dc_crtc_timing_adjust *adjust)
{
int i;
+ bool drr_unchanged;
/*
* Don't adjust DRR while there's bandwidth optimizations pending to
@@ -1356,6 +1357,19 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
}
}
+ /* timing_adjust_pending tracks whether stream->adjust still describes the
+ * OTG, so a cleared flag plus matching values means hw is already current.
+ */
+ drr_unchanged = !stream->adjust.timing_adjust_pending &&
+ stream->adjust.v_total_min == adjust->v_total_min &&
+ stream->adjust.v_total_max == adjust->v_total_max &&
+ stream->adjust.v_total_mid == adjust->v_total_mid &&
+ stream->adjust.v_total_mid_frame_num == adjust->v_total_mid_frame_num &&
+ stream->adjust.allow_otg_v_count_halt == adjust->allow_otg_v_count_halt;
+
+ if (drr_unchanged)
+ return true;
+
dc_exit_ips_for_hw_access(dc);
stream->adjust.v_total_max = adjust->v_total_max;
@@ -1366,11 +1380,13 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
if (dc->caps.max_v_total != 0 &&
(adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) {
- stream->adjust.timing_adjust_pending = false;
- if (adjust->allow_otg_v_count_halt)
+ if (adjust->allow_otg_v_count_halt) {
+ stream->adjust.timing_adjust_pending = false;
return set_long_vtotal(dc, stream, adjust);
- else
- return false;
+ }
+ /* Nothing reached hw, so stream->adjust no longer describes the OTG. */
+ stream->adjust.timing_adjust_pending = true;
+ return false;
}
for (i = 0; i < MAX_PIPES; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 21a62ca4c8dc..3d88c5c377fc 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -716,7 +716,8 @@ void set_drr_and_clear_adjust_pending(
pipe_ctx->stream_res.tg, params);
if (stream)
- stream->adjust.timing_adjust_pending = false;
+ /* A null params resets DRR in hw, leaving stream->adjust stale. */
+ stream->adjust.timing_adjust_pending = (params == NULL);
}
void get_fams2_visual_confirm_color(
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 04/17] drm/amd/display: Add HDMI RR and SCDC skips
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (2 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 03/17] drm/amd/display: only reprogram DRR when v_total values change Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 05/17] drm/amd/display: Set cursor_offload for all pipes for a given stream Roman.Li
` (13 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Ilya Bakoulin, Relja Vojvodic, Chris Park
From: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
[Why/How]
- Add debug key to avoid enabling RR by default.
- Skip SCDC access if sink or SCDC cap not present
Reviewed-by: Relja (Reggie) Vojvodic <relja.vojvodic@amd.com>
Reviewed-by: Chris Park <chris.park@amd.com>
Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/dc.h | 1 +
drivers/gpu/drm/amd/display/dc/link/link_detection.c | 4 +++-
drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c | 9 ++++++++-
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index bed0daeb0c6f..d2256c454424 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1293,6 +1293,7 @@ struct dc_debug_options {
union fw_assisted_mclk_switch_version fams_version;
union dmub_fams2_global_feature_config fams2_config;
bool fams2_imm_restore_drr;
+ bool skip_hdmi_rr_enable;
unsigned int force_cositing;
unsigned int disable_spl;
unsigned int force_easf;
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index 12fd4fd24a90..b4546f93af0c 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -1391,8 +1391,10 @@ static bool detect_link_and_local_sink(struct dc_link *link,
read_idcc_data(link->ddc, HDMI_IDCC_SCOPE_RW_CA,
link->hdmi_cable_id.raw, 0, 4);
}
- if (sink->edid_caps.rr_capable)
+
+ if (sink->edid_caps.rr_capable && !dc->debug.skip_hdmi_rr_enable)
hdmi_frl_write_read_request_enable(link->ddc);
+
/* When FreeSync is toggled through OSD,
* we see same EDID no matter what. Check MCCS caps
* to see if we should update FreeSync caps now.
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
index d87f6f377d06..3fbfc6e2594b 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
@@ -580,6 +580,9 @@ void write_scdc_data(struct ddc_service *ddc_service,
uint8_t write_buffer[2] = {0};
/*Lower than 340 Scramble bit from SCDC caps*/
+ if (!ddc_service->link->local_sink)
+ return;
+
if (ddc_service->link->local_sink &&
(ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite ||
!ddc_service->link->local_sink->edid_caps.scdc_present))
@@ -617,8 +620,12 @@ void read_scdc_data(struct ddc_service *ddc_service)
uint8_t offset = HDMI_SCDC_TMDS_CONFIG;
uint8_t tmds_config = 0;
+ if (!ddc_service->link->local_sink)
+ return;
+
if (ddc_service->link->local_sink &&
- ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite)
+ (ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite ||
+ !ddc_service->link->local_sink->edid_caps.scdc_present))
return;
link_query_ddc_data(ddc_service, slave_address, &offset,
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 05/17] drm/amd/display: Set cursor_offload for all pipes for a given stream
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (3 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 04/17] drm/amd/display: Add HDMI RR and SCDC skips Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 06/17] drm/amd/display: Refactor DMUB fast lock sequencing Roman.Li
` (12 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Alvin Lee, Nicholas Kazlauskas
From: Alvin Lee <Alvin.Lee2@amd.com>
[Description]
- When using the cursor offload path, the cursor_offload flag must
be set for each DPP and HUBP driving the stream
- Previous implementation only sets the flag in the DPP and HUBP for
the OTG master pipe
- Add helper function to populate an array of DPP's and HUBP's that need
to have the cursor_offload flag set
- This is to avoid passing in pipe_ctx to hwss execution params
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 67 ++++++++++++-------
.../gpu/drm/amd/display/dc/core/dc_stream.c | 36 ++++++----
.../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 11 ++-
.../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 11 ++-
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 57 ++++++++++------
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 10 +--
.../amd/display/dc/hwss/dcn50/dcn50_hwseq.c | 11 ++-
.../drm/amd/display/dc/hwss/hw_sequencer.h | 31 +++++----
8 files changed, 153 insertions(+), 81 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 3d88c5c377fc..4e75eb3e3dab 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -4242,6 +4242,7 @@ void hwss_begin_cursor_offload_update(struct dc *dc, union block_sequence_params
params->begin_cursor_offload_update_params.dmub,
params->begin_cursor_offload_update_params.dpp,
params->begin_cursor_offload_update_params.hubp,
+ params->begin_cursor_offload_update_params.pipe_count,
params->begin_cursor_offload_update_params.stream_idx);
}
@@ -4252,6 +4253,7 @@ void hwss_commit_cursor_offload_update(struct dc *dc, union block_sequence_param
params->commit_cursor_offload_update_params.dmub,
params->commit_cursor_offload_update_params.dpp,
params->commit_cursor_offload_update_params.hubp,
+ params->commit_cursor_offload_update_params.pipe_count,
params->commit_cursor_offload_update_params.stream_idx);
}
@@ -4273,6 +4275,7 @@ void hwss_abort_cursor_offload_update(struct dc *dc, union block_sequence_params
params->abort_cursor_offload_update_params.dmub,
params->abort_cursor_offload_update_params.dpp,
params->abort_cursor_offload_update_params.hubp,
+ params->abort_cursor_offload_update_params.pipe_count,
params->abort_cursor_offload_update_params.stream_idx);
}
@@ -5912,25 +5915,47 @@ void hwss_add_update_cursor_offload_pipe(struct block_sequence_state *seq_state,
}
}
+uint8_t hwss_build_cursor_offload_pipe_list(struct pipe_ctx *pipe_ctx,
+ struct dpp **dpp,
+ struct hubp **hubp)
+{
+ struct pipe_ctx *otg_master = resource_get_otg_master(pipe_ctx);
+ struct pipe_ctx *odm_pipe;
+ struct pipe_ctx *mpc_pipe;
+ uint8_t count = 0;
+
+ if (!otg_master)
+ return 0;
+
+ for (odm_pipe = otg_master; odm_pipe != NULL; odm_pipe = odm_pipe->next_odm_pipe) {
+ for (mpc_pipe = odm_pipe; mpc_pipe != NULL; mpc_pipe = mpc_pipe->bottom_pipe) {
+ if (count >= MAX_PIPES)
+ return count;
+ dpp[count] = mpc_pipe->plane_res.dpp;
+ hubp[count] = mpc_pipe->plane_res.hubp;
+ count++;
+ }
+ }
+
+ return count;
+}
+
void hwss_add_commit_cursor_offload_update(struct block_sequence_state *seq_state,
struct dc *dc,
struct pipe_ctx *pipe_ctx)
{
const struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx);
+ struct commit_cursor_offload_update_params *p;
if (!top_pipe)
return;
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
seq_state->steps[*seq_state->num_steps].func = HWSS_COMMIT_CURSOR_OFFLOAD_UPDATE;
- seq_state->steps[*seq_state->num_steps].params.commit_cursor_offload_update_params.dmub =
- dc->ctx->dmub_srv->dmub;
- seq_state->steps[*seq_state->num_steps].params.commit_cursor_offload_update_params.stream_idx =
- top_pipe->pipe_idx;
- seq_state->steps[*seq_state->num_steps].params.commit_cursor_offload_update_params.dpp =
- pipe_ctx->plane_res.dpp;
- seq_state->steps[*seq_state->num_steps].params.commit_cursor_offload_update_params.hubp =
- pipe_ctx->plane_res.hubp;
+ p = &seq_state->steps[*seq_state->num_steps].params.commit_cursor_offload_update_params;
+ p->dmub = dc->ctx->dmub_srv->dmub;
+ p->stream_idx = top_pipe->pipe_idx;
+ p->pipe_count = hwss_build_cursor_offload_pipe_list(pipe_ctx, p->dpp, p->hubp);
(*seq_state->num_steps)++;
}
}
@@ -5940,20 +5965,17 @@ void hwss_add_begin_cursor_offload_update(struct block_sequence_state *seq_state
struct pipe_ctx *pipe_ctx)
{
const struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx);
+ struct begin_cursor_offload_update_params *p;
if (!top_pipe)
return;
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
seq_state->steps[*seq_state->num_steps].func = HWSS_BEGIN_CURSOR_OFFLOAD_UPDATE;
- seq_state->steps[*seq_state->num_steps].params.begin_cursor_offload_update_params.dmub =
- dc->ctx->dmub_srv->dmub;
- seq_state->steps[*seq_state->num_steps].params.begin_cursor_offload_update_params.stream_idx =
- top_pipe->pipe_idx;
- seq_state->steps[*seq_state->num_steps].params.begin_cursor_offload_update_params.dpp =
- pipe_ctx->plane_res.dpp;
- seq_state->steps[*seq_state->num_steps].params.begin_cursor_offload_update_params.hubp =
- pipe_ctx->plane_res.hubp;
+ p = &seq_state->steps[*seq_state->num_steps].params.begin_cursor_offload_update_params;
+ p->dmub = dc->ctx->dmub_srv->dmub;
+ p->stream_idx = top_pipe->pipe_idx;
+ p->pipe_count = hwss_build_cursor_offload_pipe_list(pipe_ctx, p->dpp, p->hubp);
(*seq_state->num_steps)++;
}
}
@@ -5963,20 +5985,17 @@ void hwss_add_abort_cursor_offload_update(struct block_sequence_state *seq_state
struct pipe_ctx *pipe_ctx)
{
const struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx);
+ struct abort_cursor_offload_update_params *p;
if (!top_pipe)
return;
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
seq_state->steps[*seq_state->num_steps].func = ABORT_CURSOR_OFFLOAD_UPDATE;
- seq_state->steps[*seq_state->num_steps].params.abort_cursor_offload_update_params.dmub =
- dc->ctx->dmub_srv->dmub;
- seq_state->steps[*seq_state->num_steps].params.abort_cursor_offload_update_params.stream_idx =
- top_pipe->pipe_idx;
- seq_state->steps[*seq_state->num_steps].params.abort_cursor_offload_update_params.dpp =
- pipe_ctx->plane_res.dpp;
- seq_state->steps[*seq_state->num_steps].params.abort_cursor_offload_update_params.hubp =
- pipe_ctx->plane_res.hubp;
+ p = &seq_state->steps[*seq_state->num_steps].params.abort_cursor_offload_update_params;
+ p->dmub = dc->ctx->dmub_srv->dmub;
+ p->stream_idx = top_pipe->pipe_idx;
+ p->pipe_count = hwss_build_cursor_offload_pipe_list(pipe_ctx, p->dpp, p->hubp);
(*seq_state->num_steps)++;
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 6b01db8b32d0..d92c51b01272 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -309,6 +309,9 @@ void program_cursor_attributes(
struct pipe_ctx *pipe_to_program = NULL;
bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc);
bool unlock_dmub = false;
+ struct dpp *dpp[MAX_PIPES];
+ struct hubp *hubp[MAX_PIPES];
+ uint8_t pipe_count = 0;
if (!stream)
return;
@@ -327,10 +330,13 @@ void program_cursor_attributes(
if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) {
struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx);
- if (top_pipe)
+ if (top_pipe) {
+ pipe_count =
+ hwss_build_cursor_offload_pipe_list(pipe_ctx, dpp, hubp);
+
dc->hwss.begin_cursor_offload_update(dc->ctx->dmub_srv->dmub,
- pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp,
- top_pipe->pipe_idx);
+ dpp, hubp, pipe_count, top_pipe->pipe_idx);
+ }
} else {
if (dc->hwss.dmub_hw_control_lock && pipe_ctx->stream &&
should_use_dmub_inbox0_lock_for_link(dc, pipe_ctx->stream->link)) {
@@ -362,10 +368,10 @@ void program_cursor_attributes(
if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update) {
struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_to_program);
- if (top_pipe)
+ if (top_pipe) {
dc->hwss.commit_cursor_offload_update(dc->ctx->dmub_srv->dmub,
- pipe_to_program->plane_res.dpp, pipe_to_program->plane_res.hubp,
- top_pipe->pipe_idx);
+ dpp, hubp, pipe_count, top_pipe->pipe_idx);
+ }
} else {
dc->hwss.cursor_lock(dc, pipe_to_program, false);
if (pipe_to_program->next_odm_pipe)
@@ -493,6 +499,9 @@ void program_cursor_position(
struct pipe_ctx *pipe_to_program = NULL;
bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc);
bool unlock_dmub = false;
+ struct dpp *dpp[MAX_PIPES];
+ struct hubp *hubp[MAX_PIPES];
+ uint8_t pipe_count = 0;
if (!stream)
return;
@@ -515,10 +524,13 @@ void program_cursor_position(
if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) {
struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx);
- if (top_pipe)
+ if (top_pipe) {
+ pipe_count =
+ hwss_build_cursor_offload_pipe_list(pipe_ctx, dpp, hubp);
+
dc->hwss.begin_cursor_offload_update(dc->ctx->dmub_srv->dmub,
- pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp,
- top_pipe->pipe_idx);
+ dpp, hubp, pipe_count, top_pipe->pipe_idx);
+ }
} else {
if (dc->hwss.dmub_hw_control_lock && pipe_ctx->stream &&
should_use_dmub_inbox0_lock_for_link(dc, pipe_ctx->stream->link)) {
@@ -547,10 +559,10 @@ void program_cursor_position(
if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update) {
struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_to_program);
- if (top_pipe)
+ if (top_pipe) {
dc->hwss.commit_cursor_offload_update(dc->ctx->dmub_srv->dmub,
- pipe_to_program->plane_res.dpp, pipe_to_program->plane_res.hubp,
- top_pipe->pipe_idx);
+ dpp, hubp, pipe_count, top_pipe->pipe_idx);
+ }
} else {
dc->hwss.cursor_lock(dc, pipe_to_program, false);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index 33f7ab4c6c15..771555ec1431 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -3168,11 +3168,16 @@ static void dcn10_update_dchubp_dpp(
if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
if (dc_dmub_srv_is_cursor_offload_enabled(dc) && dc->hwss.abort_cursor_offload_update) {
struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx);
+ struct dpp *dpp[MAX_PIPES];
+ struct hubp *hubp[MAX_PIPES];
+
+ if (top_pipe) {
+ uint8_t pipe_count =
+ hwss_build_cursor_offload_pipe_list(pipe_ctx, dpp, hubp);
- if (top_pipe)
dc->hwss.abort_cursor_offload_update(dc->ctx->dmub_srv->dmub,
- pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp,
- top_pipe->pipe_idx);
+ dpp, hubp, pipe_count, top_pipe->pipe_idx);
+ }
}
dc->hwss.set_cursor_attribute(pipe_ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index f408589072d7..e8b9495c799f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -1840,11 +1840,16 @@ void dcn20_update_dchubp_dpp(
pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
if (dc_dmub_srv_is_cursor_offload_enabled(dc) && dc->hwss.abort_cursor_offload_update) {
struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx);
+ struct dpp *dpp[MAX_PIPES];
+ struct hubp *hubp[MAX_PIPES];
+
+ if (top_pipe) {
+ uint8_t pipe_count =
+ hwss_build_cursor_offload_pipe_list(pipe_ctx, dpp, hubp);
- if (top_pipe)
dc->hwss.abort_cursor_offload_update(dc->ctx->dmub_srv->dmub,
- pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp,
- top_pipe->pipe_idx);
+ dpp, hubp, pipe_count, top_pipe->pipe_idx);
+ }
}
dc->hwss.set_cursor_attribute(pipe_ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index a959d8c37b6a..41abfff6cf47 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -1646,9 +1646,30 @@ void dcn35_hardware_release(struct dc *dc)
dc->hwss.hw_block_power_up(dc, &pg_update_state);
}
-void dcn35_abort_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, struct hubp *hubp, uint32_t stream_idx)
+/* Set the cursor offload flag on every resolved hubp/dpp in the pipe tree. */
+static void dcn35_set_cursor_offload(struct dpp **dpp, struct hubp **hubp,
+ uint8_t pipe_count, bool enable)
{
- struct dc *dc = dpp->ctx->dc;
+ uint8_t i;
+
+ for (i = 0; i < pipe_count; i++) {
+ if (hubp[i])
+ hubp[i]->cursor_offload = enable;
+ if (dpp[i])
+ dpp[i]->cursor_offload = enable;
+ }
+}
+
+void dcn35_abort_cursor_offload_update(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx)
+{
+ struct dc *dc;
+ uint8_t i;
+
+ if (pipe_count == 0 || dpp[0] == NULL)
+ return;
+
+ dc = dpp[0]->ctx->dc;
/*
* Insert a blank update to modify the write index and set pipe_mask to 0.
@@ -1667,10 +1688,10 @@ void dcn35_abort_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, s
*/
if (dc->hwss.begin_cursor_offload_update)
- dc->hwss.begin_cursor_offload_update(dmub, dpp, hubp, stream_idx);
+ dc->hwss.begin_cursor_offload_update(dmub, dpp, hubp, pipe_count, stream_idx);
if (dc->hwss.commit_cursor_offload_update)
- dc->hwss.commit_cursor_offload_update(dmub, dpp, hubp, stream_idx);
+ dc->hwss.commit_cursor_offload_update(dmub, dpp, hubp, pipe_count, stream_idx);
/*
* The aborted payload is dropped by firmware, so resync the SW cursor
@@ -1678,13 +1699,16 @@ void dcn35_abort_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, s
* set_cursor_position re-program CURSOR_ENABLE instead of skipping it
* because of a stale cache.
*/
- if (dpp->funcs->refresh_cursor_state)
- dpp->funcs->refresh_cursor_state(dpp);
- if (hubp && hubp->funcs->refresh_cursor_state)
- hubp->funcs->refresh_cursor_state(hubp);
+ for (i = 0; i < pipe_count; i++) {
+ if (dpp[i] && dpp[i]->funcs->refresh_cursor_state)
+ dpp[i]->funcs->refresh_cursor_state(dpp[i]);
+ if (hubp[i] && hubp[i]->funcs->refresh_cursor_state)
+ hubp[i]->funcs->refresh_cursor_state(hubp[i]);
+ }
}
-void dcn35_begin_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, struct hubp *hubp, uint32_t stream_idx)
+void dcn35_begin_cursor_offload_update(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx)
{
volatile struct dmub_cursor_offload_v1 *cs = dmub->cursor_offload_v1;
uint32_t write_idx, payload_idx;
@@ -1695,24 +1719,17 @@ void dcn35_begin_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, s
cs->offload_streams[stream_idx].payloads[payload_idx].write_idx_start = write_idx;
cs->offload_streams[stream_idx].payloads[payload_idx].pipe_mask = 0;
- if (hubp)
- hubp->cursor_offload = true;
-
- if (dpp)
- dpp->cursor_offload = true;
+ dcn35_set_cursor_offload(dpp, hubp, pipe_count, true);
}
-void dcn35_commit_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, struct hubp *hubp, uint32_t stream_idx)
+void dcn35_commit_cursor_offload_update(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx)
{
volatile struct dmub_cursor_offload_v1 *cs = dmub->cursor_offload_v1;
volatile struct dmub_shared_state_cursor_offload_stream_v1 *shared_stream;
uint32_t write_idx, payload_idx;
- if (hubp)
- hubp->cursor_offload = false;
-
- if (dpp)
- dpp->cursor_offload = false;
+ dcn35_set_cursor_offload(dpp, hubp, pipe_count, false);
write_idx = cs->offload_streams[stream_idx].write_idx + 1; /* new payload (+1) */
payload_idx = write_idx % ARRAY_SIZE(cs->offload_streams[stream_idx].payloads);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
index 9f779e408ec6..d47f7232f863 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
@@ -105,10 +105,12 @@ bool dcn35_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);
void dcn35_hardware_release(struct dc *dc);
-void dcn35_abort_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, struct hubp *hubp, uint32_t stream_idx);
-void dcn35_begin_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, struct hubp *hubp, uint32_t stream_idx);
-void dcn35_commit_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp,
- struct hubp *hubp, uint32_t stream_idx);
+void dcn35_abort_cursor_offload_update(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx);
+void dcn35_begin_cursor_offload_update(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx);
+void dcn35_commit_cursor_offload_update(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx);
void dcn35_update_cursor_offload_pipe(struct dmub_srv *dmub, uint32_t stream_idx,
uint8_t pipe_idx, const struct dpp *dpp, const struct hubp *hubp);
void dcn35_notify_cursor_offload_drr_update(struct dc *dc, struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c
index 0361c520b7d9..7a82aaa6d1d6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c
@@ -204,11 +204,16 @@ void dcn50_update_dchubp_dpp(
pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
if (dc_dmub_srv_is_cursor_offload_enabled(dc) && dc->hwss.abort_cursor_offload_update) {
struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx);
+ struct dpp *dpp[MAX_PIPES];
+ struct hubp *hubp[MAX_PIPES];
+
+ if (top_pipe) {
+ uint8_t pipe_count =
+ hwss_build_cursor_offload_pipe_list(pipe_ctx, dpp, hubp);
- if (top_pipe)
dc->hwss.abort_cursor_offload_update(dc->ctx->dmub_srv->dmub,
- pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp,
- top_pipe->pipe_idx);
+ dpp, hubp, pipe_count, top_pipe->pipe_idx);
+ }
}
dc->hwss.set_cursor_attribute(pipe_ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index c0c098b5bcaa..de7a12c706ac 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -887,8 +887,9 @@ struct phantom_hubp_post_enable_params {
struct begin_cursor_offload_update_params {
struct dmub_srv *dmub;
- struct dpp *dpp;
- struct hubp *hubp;
+ struct dpp *dpp[MAX_PIPES];
+ struct hubp *hubp[MAX_PIPES];
+ uint8_t pipe_count;
uint32_t stream_idx;
};
@@ -902,15 +903,17 @@ struct update_cursor_offload_pipe_params {
struct commit_cursor_offload_update_params {
struct dmub_srv *dmub;
- struct dpp *dpp;
- struct hubp *hubp;
+ struct dpp *dpp[MAX_PIPES];
+ struct hubp *hubp[MAX_PIPES];
+ uint8_t pipe_count;
uint32_t stream_idx;
};
struct abort_cursor_offload_update_params {
struct dmub_srv *dmub;
- struct dpp *dpp;
- struct hubp *hubp;
+ struct dpp *dpp[MAX_PIPES];
+ struct hubp *hubp[MAX_PIPES];
+ uint8_t pipe_count;
uint32_t stream_idx;
};
@@ -1526,12 +1529,12 @@ struct hw_sequencer_funcs {
void (*set_cursor_position_legacy)(struct pipe_ctx *pipe);
void (*set_cursor_attribute)(struct pipe_ctx *pipe);
void (*set_cursor_sdr_white_level)(struct pipe_ctx *pipe);
- void (*abort_cursor_offload_update)(struct dmub_srv *dmub, struct dpp *dpp,
- struct hubp *hubp, uint32_t stream_idx);
- void (*begin_cursor_offload_update)(struct dmub_srv *dmub, struct dpp *dpp,
- struct hubp *hubp, uint32_t stream_idx);
- void (*commit_cursor_offload_update)(struct dmub_srv *dmub, struct dpp *dpp,
- struct hubp *hubp, uint32_t stream_idx);
+ void (*abort_cursor_offload_update)(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx);
+ void (*begin_cursor_offload_update)(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx);
+ void (*commit_cursor_offload_update)(struct dmub_srv *dmub, struct dpp **dpp,
+ struct hubp **hubp, uint8_t pipe_count, uint32_t stream_idx);
void (*update_cursor_offload_pipe)(struct dmub_srv *dmub,
uint32_t stream_idx,
uint8_t pipe_idx,
@@ -2655,6 +2658,10 @@ void hwss_add_opp_program_left_edge_extra_pixel(struct block_sequence_state *seq
void hwss_add_hubp_enable_3dlut_fl(struct block_sequence_state *seq_state,
struct hubp *hubp);
+uint8_t hwss_build_cursor_offload_pipe_list(struct pipe_ctx *pipe_ctx,
+ struct dpp **dpp,
+ struct hubp **hubp);
+
void hwss_add_begin_cursor_offload_update(struct block_sequence_state *seq_state,
struct dc *dc,
struct pipe_ctx *pipe_ctx);
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 06/17] drm/amd/display: Refactor DMUB fast lock sequencing
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (4 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 05/17] drm/amd/display: Set cursor_offload for all pipes for a given stream Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 07/17] drm/amd/display: Skip link off frame count for general UI Roman.Li
` (11 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Rafal Ostrowski, Alvin Lee
From: Rafal Ostrowski <rafal.ostrowski@amd.com>
[WHY]
Resolve fast-lock policy before execution and avoid queuing no-op
steps. Remove duplicated per-ASIC command construction.
[HOW]
Use one fast-lock opcode, parameter structure and executor.
Capture the service handle and precomputed Inbox0 command.
Keep separate SubVP and generic capability hooks and preserve
the lock manager's original support and split feature gates.
Retain the unused SubVP enumerator and existing opcode values.
Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Rafal Ostrowski <rafal.ostrowski@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 103 +++++++++++-------
.../drm/amd/display/dc/dce/dmub_hw_lock_mgr.c | 12 +-
.../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 18 +--
.../amd/display/dc/hwss/dcn32/dcn32_hwseq.h | 2 +-
.../amd/display/dc/hwss/dcn32/dcn32_init.c | 2 +-
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 28 ++---
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 2 +-
.../amd/display/dc/hwss/dcn35/dcn35_init.c | 2 +
.../amd/display/dc/hwss/dcn351/dcn351_init.c | 2 +
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 16 +--
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 2 +-
.../amd/display/dc/hwss/dcn401/dcn401_init.c | 2 +-
.../amd/display/dc/hwss/dcn42/dcn42_hwseq.c | 16 +--
.../amd/display/dc/hwss/dcn42/dcn42_hwseq.h | 2 +-
.../amd/display/dc/hwss/dcn42/dcn42_init.c | 2 +-
.../amd/display/dc/hwss/dcn60/dcn60_init.c | 2 +-
.../drm/amd/display/dc/hwss/hw_sequencer.h | 22 ++--
17 files changed, 106 insertions(+), 129 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 4e75eb3e3dab..47efe05fe9bb 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -43,6 +43,51 @@
#include "link_service.h"
#include "custom_float.h"
+static union dmub_inbox0_cmd_lock_hw hwss_build_dmub_lock_command(bool lock)
+{
+ union dmub_inbox0_cmd_lock_hw command = { 0 };
+
+ command.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
+ command.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
+ command.bits.lock = lock;
+ command.bits.should_release = !lock;
+
+ return command;
+}
+
+void hwss_add_dmub_hw_control_lock_fast(struct block_sequence_state *seq_state,
+ struct dc *dc, bool lock)
+{
+ struct dmub_hw_control_lock_fast_params *params;
+
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps || !dc || !dc->ctx ||
+ !dc->ctx->dmub_srv || !dc->ctx->dmub_srv->dmub ||
+ *seq_state->num_steps >= MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+ /* Dropping a lock or unlock step can leave the pair unbalanced. */
+ ASSERT(!seq_state || !seq_state->num_steps ||
+ *seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE);
+ return;
+ }
+
+ params = &seq_state->steps[*seq_state->num_steps].params.dmub_hw_control_lock_fast_params;
+ params->dmub_srv = dc->ctx->dmub_srv;
+ params->command = hwss_build_dmub_lock_command(lock);
+ seq_state->steps[(*seq_state->num_steps)++].func = DMUB_HW_CONTROL_LOCK_FAST;
+}
+
+void hwss_dmub_hw_control_lock_fast(union block_sequence_params *params)
+{
+ struct dmub_hw_control_lock_fast_params *p;
+
+ if (!params)
+ return;
+
+ p = ¶ms->dmub_hw_control_lock_fast_params;
+
+ if (p->dmub_srv && p->dmub_srv->dmub)
+ dmub_hw_lock_mgr_inbox0_cmd(p->dmub_srv, p->command);
+}
+
#define MAX_NUM_MCACHE 8
/* used as index in array of black_color_format */
@@ -1207,27 +1252,21 @@ void hwss_build_fast_sequence(struct dc *dc,
block_sequence[*num_steps].func = HUBP_WAIT_FOR_DCC_META_PROP;
(*num_steps)++;
}
- if (dc->hwss.subvp_pipe_control_lock_fast) {
- block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
- block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true;
- block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.subvp_immediate_flip =
- plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN;
- block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
- (*num_steps)++;
- }
- if (dc->hwss.dmub_hw_control_lock_fast) {
- is_dmub_lock_required = dc_state_is_fams2_in_use(dc, context) ||
- dmub_hw_lock_mgr_does_link_require_lock(dc, stream->link);
- block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.dc = dc;
- block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.lock = true;
- block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.is_required = is_dmub_lock_required;
- block_sequence[*num_steps].func = DMUB_HW_CONTROL_LOCK_FAST;
- (*num_steps)++;
+ if (plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN &&
+ dc->hwss.is_subvp_hw_lock_supported && dc->hwss.is_subvp_hw_lock_supported(dc))
+ is_dmub_lock_required = true;
+
+ if (dc->hwss.is_dmub_hw_lock_supported && dc->hwss.is_dmub_hw_lock_supported(dc)) {
+ /* is_dmub_lock_required is reused by the matching unlock step below. */
+ is_dmub_lock_required |= dc_state_is_fams2_in_use(dc, context) ||
+ dmub_hw_lock_mgr_does_link_require_lock(dc, stream->link);
}
- hwss_add_optc_pipe_control_lock(
- &(struct block_sequence_state){ block_sequence, num_steps },
- dc, pipe_ctx, true);
+
+ if (is_dmub_lock_required)
+ hwss_add_dmub_hw_control_lock_fast(&seq_state, dc, true);
+
+ hwss_add_optc_pipe_control_lock(&seq_state, dc, pipe_ctx, true);
for (i = 0; i < dmub_cmd_count; i++) {
block_sequence[*num_steps].params.send_dmcub_cmd_params.ctx = dc->ctx;
@@ -1622,24 +1661,9 @@ void hwss_build_fast_sequence(struct dc *dc,
current_pipe = current_pipe->next_odm_pipe;
}
- hwss_add_optc_pipe_control_lock(
- &(struct block_sequence_state){ block_sequence, num_steps },
- dc, pipe_ctx, false);
- if (dc->hwss.subvp_pipe_control_lock_fast) {
- block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
- block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = false;
- block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.subvp_immediate_flip =
- plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN;
- block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
- (*num_steps)++;
- }
- if (dc->hwss.dmub_hw_control_lock_fast) {
- block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.dc = dc;
- block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.lock = false;
- block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.is_required = is_dmub_lock_required;
- block_sequence[*num_steps].func = DMUB_HW_CONTROL_LOCK_FAST;
- (*num_steps)++;
- }
+ hwss_add_optc_pipe_control_lock(&seq_state, dc, pipe_ctx, false);
+ if (is_dmub_lock_required)
+ hwss_add_dmub_hw_control_lock_fast(&seq_state, dc, false);
current_pipe = pipe_ctx;
while (current_pipe) {
@@ -1677,9 +1701,6 @@ void hwss_execute_sequence(struct dc *dc,
params = &(block_sequence[i].params);
switch (block_sequence[i].func) {
- case DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST:
- dc->hwss.subvp_pipe_control_lock_fast(params);
- break;
case TG_LOCK:
dc->hwss.tg_lock(¶ms->tg_lock_params);
break;
@@ -1774,7 +1795,7 @@ void hwss_execute_sequence(struct dc *dc,
dc->hwss.wait_for_dcc_meta_propagation(params->wait_for_dcc_meta_propagation_params.delay);
break;
case DMUB_HW_CONTROL_LOCK_FAST:
- dc->hwss.dmub_hw_control_lock_fast(params);
+ hwss_dmub_hw_control_lock_fast(params);
break;
case HUBP_PROGRAM_SURFACE_CONFIG:
hwss_program_surface_config(params);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
index 2ac1485a3438..f5ff61a2e89e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
@@ -30,17 +30,17 @@
static bool dmub_hw_lock_has_inbox0_lock(const struct dc *dc)
{
- return dc->ctx && dc->ctx->dmub_srv &&
- dc->hwss.dmub_hw_control_lock &&
- dc->hwss.dmub_hw_control_lock_fast &&
- dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support;
+ return dc && dc->ctx && dc->ctx->dmub_srv && dc->ctx->dmub_srv->dmub &&
+ dc->hwss.dmub_hw_control_lock &&
+ dc->hwss.is_dmub_hw_lock_supported &&
+ dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support;
}
static bool dmub_hw_lock_has_inbox0_lock_split(const struct dc *dc)
{
- return dc->ctx && dc->ctx->dmub_srv &&
+ return dc && dc->ctx && dc->ctx->dmub_srv && dc->ctx->dmub_srv->dmub &&
dc->hwss.dmub_hw_control_lock &&
- dc->hwss.dmub_hw_control_lock_fast &&
+ dc->hwss.is_dmub_hw_lock_supported &&
dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_split;
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index 8e45ad4191c7..10361f3b6122 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -425,22 +425,10 @@ void dcn32_subvp_pipe_control_lock(struct dc *dc,
}
}
-void dcn32_subvp_pipe_control_lock_fast(union block_sequence_params *params)
+bool dcn32_is_subvp_hw_lock_supported(const struct dc *dc)
{
- struct dc *dc = params->subvp_pipe_control_lock_fast_params.dc;
- bool lock = params->subvp_pipe_control_lock_fast_params.lock;
- bool subvp_immediate_flip = params->subvp_pipe_control_lock_fast_params.subvp_immediate_flip;
-
- // Don't need to lock for DRR VSYNC flips -- FW will wait for DRR pending update cleared.
- if (subvp_immediate_flip) {
- union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
-
- hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
- hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
- hw_lock_cmd.bits.lock = lock;
- hw_lock_cmd.bits.should_release = !lock;
- dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
- }
+ /* SubVP inbox0 lock has no firmware feature gate on this generation. */
+ return dc && dc->ctx && dc->ctx->dmub_srv && dc->ctx->dmub_srv->dmub;
}
bool dcn32_set_mpc_shaper_3dlut(struct dpp *dpp, struct mpc *mpc,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
index c85ff14596af..734727015b3f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
@@ -82,7 +82,7 @@ void dcn32_subvp_pipe_control_lock(struct dc *dc,
struct pipe_ctx *top_pipe_to_program,
bool subvp_prev_use);
-void dcn32_subvp_pipe_control_lock_fast(union block_sequence_params *params);
+bool dcn32_is_subvp_hw_lock_supported(const struct dc *dc);
void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link_settings *link_settings);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
index 9d3c7b40b21f..b755df909871 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
@@ -118,7 +118,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.disable_phantom_streams = dcn32_disable_phantom_streams,
.subvp_pipe_control_lock = dcn32_subvp_pipe_control_lock,
.update_visual_confirm_color = dcn10_update_visual_confirm_color,
- .subvp_pipe_control_lock_fast = dcn32_subvp_pipe_control_lock_fast,
+ .is_subvp_hw_lock_supported = dcn32_is_subvp_hw_lock_supported,
.update_phantom_vp_position = dcn32_update_phantom_vp_position,
.update_dsc_pg = dcn32_update_dsc_pg,
.apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index 41abfff6cf47..f2bf7d1ca4f7 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -1855,11 +1855,7 @@ bool dcn35_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lo
{
union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
- if (!dc->ctx || !dc->ctx->dmub_srv)
- return false;
-
- /* if not support inbox0 lock, would not use inbox0 lock mechanism */
- if (!dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support)
+ if (!dcn35_is_dmub_hw_lock_supported(dc))
return false;
if (lock) {
@@ -1877,22 +1873,12 @@ bool dcn35_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lo
return true;
}
-void dcn35_dmub_hw_control_lock_fast(union block_sequence_params *params)
+bool dcn35_is_dmub_hw_lock_supported(const struct dc *dc)
{
- struct dc *dc = params->dmub_hw_control_lock_fast_params.dc;
- bool lock = params->dmub_hw_control_lock_fast_params.lock;
-
- /* if not support inbox0 lock, would not use inbox0 lock mechanism */
- if (!dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support)
- return;
-
- if (params->dmub_hw_control_lock_fast_params.is_required) {
- union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
+ if (!dc || !dc->ctx || !dc->ctx->dmub_srv || !dc->ctx->dmub_srv->dmub)
+ return false;
- hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
- hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
- hw_lock_cmd.bits.lock = lock;
- hw_lock_cmd.bits.should_release = !lock;
- dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
- }
+ /* if not support inbox0 lock, would not use inbox0 lock mechanism */
+ return dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support != 0;
}
+
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
index d47f7232f863..96b836b2ae71 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
@@ -120,6 +120,6 @@ void dcn35_disable_link_output(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal);
bool dcn35_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock);
-void dcn35_dmub_hw_control_lock_fast(union block_sequence_params *params);
+bool dcn35_is_dmub_hw_lock_supported(const struct dc *dc);
#endif /* __DC_HWSS_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
index b1933a80fc47..f8c8ab12bdf9 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
@@ -137,6 +137,8 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
.update_dchubp_dpp = dcn20_update_dchubp_dpp,
.post_unlock_reset_opp = dcn20_post_unlock_reset_opp,
.get_underflow_debug_data = dcn30_get_underflow_debug_data,
+ .dmub_hw_control_lock = dcn35_dmub_hw_control_lock,
+ .is_dmub_hw_lock_supported = dcn35_is_dmub_hw_lock_supported,
};
static const struct hwseq_private_funcs dcn35_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
index dbd8480b9e05..82a8d87f9428 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
@@ -126,6 +126,8 @@ static const struct hw_sequencer_funcs dcn351_funcs = {
.calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
.get_underflow_debug_data = dcn30_get_underflow_debug_data,
+ .dmub_hw_control_lock = dcn35_dmub_hw_control_lock,
+ .is_dmub_hw_lock_supported = dcn35_is_dmub_hw_lock_supported,
};
static const struct hwseq_private_funcs dcn351_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 73f969fd1b33..379902bdef0a 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -1635,20 +1635,10 @@ bool dcn401_dmub_hw_control_lock(struct dc *dc,
return true;
}
-void dcn401_dmub_hw_control_lock_fast(union block_sequence_params *params)
+bool dcn401_is_dmub_hw_lock_supported(const struct dc *dc)
{
- struct dc *dc = params->dmub_hw_control_lock_fast_params.dc;
- bool lock = params->dmub_hw_control_lock_fast_params.lock;
-
- if (params->dmub_hw_control_lock_fast_params.is_required) {
- union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
-
- hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
- hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
- hw_lock_cmd.bits.lock = lock;
- hw_lock_cmd.bits.should_release = !lock;
- dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
- }
+ /* Inbox0 HW lock is unconditionally available on this generation. */
+ return dc && dc->ctx && dc->ctx->dmub_srv && dc->ctx->dmub_srv->dmub;
}
void dcn401_fams2_update_config(struct dc *dc, struct dc_state *context, bool enable)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
index 66a0fc8de8ba..ecaeb192bca3 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
@@ -87,7 +87,7 @@ bool dcn401_dmub_hw_control_lock(struct dc *dc,
struct dc_state *context,
bool lock);
void dcn401_fams2_update_config(struct dc *dc, struct dc_state *context, bool enable);
-void dcn401_dmub_hw_control_lock_fast(union block_sequence_params *params);
+bool dcn401_is_dmub_hw_lock_supported(const struct dc *dc);
void dcn401_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings);
void dcn401_hardware_release(struct dc *dc);
void dcn401_update_odm(struct dc *dc, struct dc_state *context,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
index 2d3c46c4e00c..1a387e52218d 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
@@ -111,7 +111,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
.is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
.dmub_hw_control_lock = dcn401_dmub_hw_control_lock,
.fams2_update_config = dcn401_fams2_update_config,
- .dmub_hw_control_lock_fast = dcn401_dmub_hw_control_lock_fast,
+ .is_dmub_hw_lock_supported = dcn401_is_dmub_hw_lock_supported,
.program_outstanding_updates = dcn401_program_outstanding_updates,
.wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
.detect_pipe_changes = dcn401_detect_pipe_changes,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
index 21c3d108abe9..34bfe62296e6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
@@ -1212,20 +1212,10 @@ bool dcn42_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lo
return true;
}
-void dcn42_dmub_hw_control_lock_fast(union block_sequence_params *params)
+bool dcn42_is_dmub_hw_lock_supported(const struct dc *dc)
{
- struct dc *dc = params->dmub_hw_control_lock_fast_params.dc;
- bool lock = params->dmub_hw_control_lock_fast_params.lock;
-
- /* Use helper to check PSR/Replay for the given stream in fast path */
- if (params->dmub_hw_control_lock_fast_params.is_required) {
- union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
- hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
- hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
- hw_lock_cmd.bits.lock = lock;
- hw_lock_cmd.bits.should_release = !lock;
- dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
- }
+ /* Inbox0 HW lock is unconditionally available on this generation. */
+ return dc && dc->ctx && dc->ctx->dmub_srv && dc->ctx->dmub_srv->dmub;
}
/* In headless boot cases, DIG may be turned
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
index 31b92274a2f5..2e5523617f29 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
@@ -44,7 +44,7 @@ void dcn42_hw_block_power_up(struct dc *dc,
void dcn42_root_clock_control(struct dc *dc,
struct pg_block_update *update_state, bool power_on);
bool dcn42_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock);
-void dcn42_dmub_hw_control_lock_fast(union block_sequence_params *params);
+bool dcn42_is_dmub_hw_lock_supported(const struct dc *dc);
void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc);
void dcn42_power_down_on_boot(struct dc *dc);
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
index a28149411821..775da50e945e 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
@@ -111,7 +111,7 @@ static const struct hw_sequencer_funcs dcn42_funcs = {
.is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
.dmub_hw_control_lock = dcn42_dmub_hw_control_lock,
.fams2_update_config = dcn401_fams2_update_config,
- .dmub_hw_control_lock_fast = dcn42_dmub_hw_control_lock_fast,
+ .is_dmub_hw_lock_supported = dcn42_is_dmub_hw_lock_supported,
.program_outstanding_updates = dcn401_program_outstanding_updates,
.wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
.detect_pipe_changes = dcn401_detect_pipe_changes,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
index c89051a542cb..80125c3596ce 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
@@ -113,7 +113,7 @@ static const struct hw_sequencer_funcs dcn60_funcs = {
.is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
.dmub_hw_control_lock = dcn401_dmub_hw_control_lock,
.fams2_update_config = dcn401_fams2_update_config,
- .dmub_hw_control_lock_fast = dcn401_dmub_hw_control_lock_fast,
+ .is_dmub_hw_lock_supported = dcn401_is_dmub_hw_lock_supported,
.program_outstanding_updates = dcn401_program_outstanding_updates,
.wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
.detect_pipe_changes = dcn401_detect_pipe_changes,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index de7a12c706ac..a1b994edf80a 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -35,6 +35,7 @@
#include "inc/hw/dchubbub.h"
#include "dsc/dsc.h"
#include "link_service_types.h"
+#include "dmub/inc/dmub_cmd.h"
struct pipe_ctx;
struct dc_state;
@@ -62,11 +63,6 @@ struct hpo_frl_stream_encoder;
struct link_training_settings;
struct dc_link;
struct dc_crtc_timing;
-struct subvp_pipe_control_lock_fast_params {
- struct dc *dc;
- bool lock;
- bool subvp_immediate_flip;
-};
struct tg_lock_params {
struct dc *dc;
@@ -216,9 +212,8 @@ struct wait_for_dcc_meta_propagation_params {
};
struct dmub_hw_control_lock_fast_params {
- struct dc *dc;
- bool is_required;
- bool lock;
+ struct dc_dmub_srv *dmub_srv;
+ union dmub_inbox0_cmd_lock_hw command;
};
struct program_surface_config_params {
@@ -1051,7 +1046,6 @@ struct link_set_dpms_on_params {
union block_sequence_params {
struct update_plane_addr_params update_plane_addr_params;
- struct subvp_pipe_control_lock_fast_params subvp_pipe_control_lock_fast_params;
struct tg_lock_params tg_lock_params;
struct tg_3dlut_wa_unlock_params tg_3dlut_wa_unlock_params;
struct set_flip_control_gsl_params set_flip_control_gsl_params;
@@ -1222,7 +1216,7 @@ union block_sequence_params {
};
enum block_sequence_func {
- DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST = 0,
+ DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST = 0, /* not used */
TG_LOCK,
TG_3DLUT_WA_UNLOCK,
HUBP_SET_FLIP_CONTROL_GSL,
@@ -1656,7 +1650,7 @@ struct hw_sequencer_funcs {
bool should_lock_all_pipes,
struct pipe_ctx *top_pipe_to_program,
bool subvp_prev_use);
- void (*subvp_pipe_control_lock_fast)(union block_sequence_params *params);
+ bool (*is_subvp_hw_lock_supported)(const struct dc *dc);
void (*z10_restore)(const struct dc *dc);
void (*z10_save_init)(struct dc *dc);
@@ -1702,7 +1696,7 @@ struct hw_sequencer_funcs {
void (*fams2_update_config)(struct dc *dc,
struct dc_state *context,
bool enable);
- void (*dmub_hw_control_lock_fast)(union block_sequence_params *params);
+ bool (*is_dmub_hw_lock_supported)(const struct dc *dc);
void (*set_long_vtotal)(struct pipe_ctx **pipe_ctx, int num_pipes, uint32_t v_total_min, uint32_t v_total_max);
void (*program_outstanding_updates)(struct dc *dc,
struct dc_state *context);
@@ -2803,4 +2797,8 @@ void hwss_add_hubbub_program_compbuf_segments(struct block_sequence_state *seq_s
unsigned int compbuf_size,
bool safe_to_lower);
+void hwss_dmub_hw_control_lock_fast(union block_sequence_params *params);
+void hwss_add_dmub_hw_control_lock_fast(struct block_sequence_state *seq_state,
+ struct dc *dc, bool lock);
+
#endif /* __DC_HW_SEQUENCER_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 07/17] drm/amd/display: Skip link off frame count for general UI
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (5 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 06/17] drm/amd/display: Refactor DMUB fast lock sequencing Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 08/17] drm/amd/display: allow skipping link bandwidth clear Roman.Li
` (10 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Allen Li, ChunTao Tso
From: Allen Li <Allen.Li@amd.com>
[Why&How]
To improve power saving of Replay,
skip the link off frame count check for general UI in DC mode.
Also disable timing sync in the same condition.
Reviewed-by: ChunTao (Chun-Tao) Tso <chuntao.tso@amd.com>
Signed-off-by: Allen Li <Allen.Li@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/dc_types.h | 2 ++
drivers/gpu/drm/amd/display/modules/power/power_replay.c | 6 ++++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 7ff2152ff233..af241b2bd29a 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -1311,6 +1311,8 @@ struct replay_settings {
uint32_t replay_events;
/* Last ABM periodic keep-alive FFU allowed bit sent to DMUB (VESA PR) */
bool last_abm_periodic_ffu_allowed;
+ /* System is in DC mode */
+ bool system_in_dc;
};
/* To split out "global" and "per-panel" config settings.
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_replay.c b/drivers/gpu/drm/amd/display/modules/power/power_replay.c
index 7861e46c612d..666585b7e00c 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_replay.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_replay.c
@@ -338,9 +338,11 @@ static bool mod_power_update_replay_active_status(unsigned int active_replay_eve
/* General UI scenario */
if (active_replay_events & replay_event_general_ui) {
- if (replay_enable_option & pr_enable_option_general_ui)
+ if (replay_enable_option & pr_enable_option_general_ui) {
+ if (link->replay_settings.system_in_dc)
+ link->replay_settings.config.replay_timing_sync_supported = false;
return true;
- else
+ } else
return false;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 08/17] drm/amd/display: allow skipping link bandwidth clear
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (6 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 07/17] drm/amd/display: Skip link off frame count for general UI Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 09/17] drm/amd/display: Prepare DSC configuration before BLS execution Roman.Li
` (9 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Martin Tsai, Anthony Koo
From: Martin Tsai <Martin.Tsai@amd.com>
[why]
To set link bandwidth with zero could hit error protection
from Sink panel to fail link training and cause screen
corruption.
[how]
To skip link bw cleaning in two conditions:
1. eDP v1.5 or latter, because the last write will take effect.
2. Sink requires not to clear it.
Reviewed-by: Anthony Koo <anthony.koo@amd.com>
Signed-off-by: Martin Tsai <Martin.Tsai@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
.../drm/amd/display/dc/core/dc_link_exports.c | 5 +++++
drivers/gpu/drm/amd/display/dc/dc.h | 3 +++
drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 1 +
.../dc/link/protocols/link_dp_training.c | 20 ++++++++++++++-----
.../amd/display/include/link_service_types.h | 1 +
5 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
index fef857c7336b..5926e8a4f95a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
@@ -263,6 +263,11 @@ void dc_link_set_preferred_training_settings(struct dc *dc,
lt_overrides, link, skip_immediate_retrain);
}
+void dc_link_set_skip_link_bw_clear(struct dc_link *link, bool skip)
+{
+ link->preferred_training_settings.skip_link_bw_clear = skip;
+}
+
bool dc_dp_trace_is_initialized(struct dc_link *link)
{
return link->dc->link_srv->dp_trace_is_initialized(link);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index d2256c454424..957e15e4a84c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -2869,6 +2869,9 @@ void dc_link_set_preferred_training_settings(struct dc *dc,
struct dc_link *link,
bool skip_immediate_retrain);
+/* Configure the sink-specific policy for future DP link training. */
+void dc_link_set_skip_link_bw_clear(struct dc_link *link, bool skip);
+
/* return - true if FEC is supported with connected DP RX, false otherwise */
bool dc_link_is_fec_supported(const struct dc_link *link);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
index d0ba9ad67a3e..b0e91b321f43 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
@@ -203,6 +203,7 @@ struct dc_link_training_overrides {
bool *enhanced_framing;
bool *mst_enable;
bool *fec_enable;
+ bool skip_link_bw_clear;
};
union payload_table_update_status {
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
index 04eedec8a230..3be36d1063de 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
@@ -724,6 +724,8 @@ void override_training_settings(
{
uint32_t lane;
+ lt_settings->skip_link_bw_clear = overrides->skip_link_bw_clear;
+
/* Override link spread */
if (!link->dp_ss_off && overrides->downspread != NULL)
lt_settings->link_settings.link_spread = *overrides->downspread ?
@@ -1095,7 +1097,7 @@ enum dc_status dpcd_set_link_settings(
struct dc_link *link,
const struct link_training_settings *lt_settings)
{
- uint8_t rate;
+ uint8_t rate = 0;
enum dc_status status;
union down_spread_ctrl downspread = {0};
@@ -1129,7 +1131,7 @@ enum dc_status dpcd_set_link_settings(
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
lt_settings->link_settings.use_link_rate_set == true) {
- rate = 0;
+
/* WA for some MUX chips that will power down with eDP and lose supported
* link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure
* MUX chip gets link rate set back before link training.
@@ -1140,9 +1142,17 @@ enum dc_status dpcd_set_link_settings(
core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
supported_link_rates, sizeof(supported_link_rates));
}
- status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
- if (status != DC_OK)
- DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_LINK_BW_SET) failed\n", __func__, __LINE__);
+
+ /*
+ * It doesn't need to clear 0x100 in below two conditions:
+ * 1. eDP v1.5 or later, because the last write will take effect in Sink.
+ * 2. Sink requires not to clear 0x100.
+ */
+ if (!lt_settings->skip_link_bw_clear && link->dpcd_caps.edp_rev <= DP_EDP_14b) {
+ status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
+ if (status != DC_OK)
+ DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_LINK_BW_SET) failed\n", __func__, __LINE__);
+ }
status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
<_settings->link_settings.link_rate_set, 1);
diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h
index da74ed66c8f9..798d83238828 100644
--- a/drivers/gpu/drm/amd/display/include/link_service_types.h
+++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
@@ -73,6 +73,7 @@ struct link_training_settings {
enum dc_pre_emphasis *pre_emphasis;
enum dc_post_cursor2 *post_cursor2;
bool should_set_fec_ready;
+ bool skip_link_bw_clear;
union dc_dp_ffe_preset *ffe_preset;
uint16_t cr_pattern_time;
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 09/17] drm/amd/display: Prepare DSC configuration before BLS execution
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (7 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 08/17] drm/amd/display: allow skipping link bandwidth clear Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 10/17] drm/amd/display: Assign alt wa bit in fams2 cmd Roman.Li
` (8 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Rafal Ostrowski, Alvin Lee, Chris Park
From: Rafal Ostrowski <rafal.ostrowski@amd.com>
[Why]
DSC sequence operations calculated configuration during execution and
passed OPTC outputs through pointers into other sequence steps. This
coupled consumers to step storage and mixed calculation with programming.
[How]
Merge the DSC configuration operations into DSC_SET_CONFIG. Prepare
register values in each DSC instance during build and pass OPTC values
by value to timing-generator and stream-encoder operations.
Share stream composition while preserving link-update and ODM padding.
Use the correct DCN401 preparation callback and remove the legacy ops.
Validate local composition inputs and capacity, stop immediate programming
on preparation failure, and publish prepared caches only on success.
Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Reviewed-by: Chris Park <chris.park@amd.com>
Signed-off-by: Rafal Ostrowski <rafal.ostrowski@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/core/dc.c | 77 +---
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 349 ++++++++++++------
.../drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c | 48 ++-
.../drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h | 13 +-
.../drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c | 1 +
.../amd/display/dc/dsc/dcn401/dcn401_dsc.c | 34 +-
.../amd/display/dc/dsc/dcn401/dcn401_dsc.h | 5 +-
.../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c | 41 +-
.../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h | 3 +-
drivers/gpu/drm/amd/display/dc/dsc/dsc.h | 3 +-
.../amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 14 +-
.../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 14 +-
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 14 +-
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 51 +--
.../drm/amd/display/dc/hwss/hw_sequencer.h | 55 ++-
.../gpu/drm/amd/display/dc/link/link_dpms.c | 15 +-
16 files changed, 419 insertions(+), 318 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 254c2a9c1b04..ef876a24afc2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -4106,21 +4106,14 @@ static void add_update_info_frame_sequence(
static void add_link_update_dsc_config_sequence(
struct block_sequence_state *seq_state,
- struct pipe_ctx *pipe_ctx,
- struct dsc_config *dsc_cfg,
- struct dsc_optc_config *dsc_optc_cfg)
+ struct pipe_ctx *pipe_ctx)
{
struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
struct dc_stream_state *stream = pipe_ctx->stream;
- struct dc *dc = stream->ctx->dc;
- struct dccg *dccg = dc->res_pool->dccg;
struct pipe_ctx *top_pipe = pipe_ctx;
- struct pipe_ctx *odm_pipe = NULL;
- int opp_cnt = 1;
- bool should_use_dto_dscclk = false;
- struct dsc_config dsc_pps_cfg;
+ struct dsc_optc_config dsc_optc_cfg = {};
+ struct dsc_config dsc_pps_cfg = {};
uint8_t *dsc_packed_pps = stream->dsc_packed_pps;
- int last_dsc_set_config_step = 0;
if (!stream->timing.flags.DSC || !dsc)
return;
@@ -4128,60 +4121,13 @@ static void add_link_update_dsc_config_sequence(
while (top_pipe->prev_odm_pipe)
top_pipe = top_pipe->prev_odm_pipe;
- for (odm_pipe = top_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
- opp_cnt++;
-
- memset(dsc_cfg, 0, sizeof(*dsc_cfg));
- memset(dsc_optc_cfg, 0, sizeof(*dsc_optc_cfg));
-
- dsc_cfg->pic_width = (stream->timing.h_addressable +
- top_pipe->dsc_padding_params.dsc_hactive_padding +
- stream->timing.h_border_left +
- stream->timing.h_border_right) / opp_cnt;
- dsc_cfg->pic_height = stream->timing.v_addressable +
- stream->timing.v_border_top +
- stream->timing.v_border_bottom;
- dsc_cfg->pixel_encoding = stream->timing.pixel_encoding;
- dsc_cfg->color_depth = stream->timing.display_color_depth;
- dsc_cfg->is_odm = top_pipe->next_odm_pipe ? true : false;
- dsc_cfg->dc_dsc_cfg = stream->timing.dsc_cfg;
- ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h % opp_cnt == 0);
- dsc_cfg->dc_dsc_cfg.num_slices_h /= opp_cnt;
- dsc_cfg->dsc_padding = 0;
-
- if (dccg && dccg->funcs->set_dto_dscclk &&
- stream->timing.pix_clk_100hz > 480000)
- should_use_dto_dscclk = true;
-
- if (should_use_dto_dscclk)
- hwss_add_dccg_set_dto_dscclk(seq_state, dccg, dsc->inst,
- dsc_cfg->dc_dsc_cfg.num_slices_h);
-
- last_dsc_set_config_step = *seq_state->num_steps;
- hwss_add_dsc_set_config(seq_state, dsc, dsc_cfg, dsc_optc_cfg);
- hwss_add_dsc_enable_with_opp(seq_state, top_pipe);
-
- for (odm_pipe = top_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
- struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
-
- if (should_use_dto_dscclk)
- hwss_add_dccg_set_dto_dscclk(seq_state, dccg, odm_dsc->inst,
- dsc_cfg->dc_dsc_cfg.num_slices_h);
-
- last_dsc_set_config_step = *seq_state->num_steps;
- hwss_add_dsc_set_config(seq_state, odm_dsc, dsc_cfg, dsc_optc_cfg);
- hwss_add_dsc_enable_with_opp(seq_state, odm_pipe);
- }
+ if (!hwss_add_dsc_sequence_for_stream(seq_state, top_pipe, 0, &dsc_optc_cfg))
+ return;
if (dc_is_dp_signal(stream->signal) && !dp_is_128b_132b_signal(pipe_ctx))
hwss_add_stream_enc_dp_set_dsc_config(seq_state,
- pipe_ctx->stream_res.stream_enc,
- &seq_state->steps[last_dsc_set_config_step].params.dsc_set_config_simple_params.dsc_optc_cfg);
-
- hwss_add_tg_set_dsc_config(seq_state, top_pipe->stream_res.tg,
- &seq_state->steps[last_dsc_set_config_step].params.dsc_set_config_simple_params.dsc_optc_cfg, true);
+ pipe_ctx->stream_res.stream_enc, &dsc_optc_cfg);
- memset(&dsc_pps_cfg, 0, sizeof(dsc_pps_cfg));
dsc_pps_cfg.pic_width = stream->timing.h_addressable +
stream->timing.h_border_left + stream->timing.h_border_right;
dsc_pps_cfg.pic_height = stream->timing.v_addressable +
@@ -4224,7 +4170,6 @@ static void commit_planes_do_stream_update_sequence(struct dc *dc,
{
int j;
struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps };
- unsigned int dsc_cfg_index = 0;
*num_steps = 0; // Initialize to 0
// Stream updates
@@ -4295,15 +4240,7 @@ static void commit_planes_do_stream_update_sequence(struct dc *dc,
continue;
if (stream_update->dsc_config)
- if (dsc_cfg_index < MAX_PIPES) {
- struct dsc_config dsc_cfg;
- struct dsc_optc_config dsc_optc_cfg;
-
- add_link_update_dsc_config_sequence(&seq_state,
- pipe_ctx,
- &dsc_cfg,
- &dsc_optc_cfg);
- }
+ add_link_update_dsc_config_sequence(&seq_state, pipe_ctx);
if (stream_update->mst_bw_update) {
if (stream_update->mst_bw_update->is_increase)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 47efe05fe9bb..da98afee558f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -1845,9 +1845,6 @@ void hwss_execute_sequence(struct dc *dc,
case DSC_READ_STATE:
hwss_dsc_read_state(params);
break;
- case DSC_CALCULATE_AND_SET_CONFIG:
- hwss_dsc_calculate_and_set_config(params);
- break;
case DSC_ENABLE_WITH_OPP:
hwss_dsc_enable_with_opp(params);
break;
@@ -2158,9 +2155,6 @@ void hwss_execute_sequence(struct dc *dc,
case STREAM_ENC_UPDATE_DP_INFO_PACKETS:
hwss_stream_enc_update_dp_info_packets(params);
break;
- case DSC_SET_CONFIG_SIMPLE:
- hwss_dsc_set_config_simple(params);
- break;
case STREAM_ENC_DP_SET_DSC_CONFIG:
hwss_stream_enc_dp_set_dsc_config(params);
break;
@@ -3287,12 +3281,15 @@ void hwss_dccg_set_dto_dscclk(union block_sequence_params *params)
void hwss_dsc_set_config(union block_sequence_params *params)
{
- struct display_stream_compressor *dsc = params->dsc_set_config_params.dsc;
- struct dsc_config *dsc_cfg = params->dsc_set_config_params.dsc_cfg;
- struct dsc_optc_config *dsc_optc_cfg = params->dsc_set_config_params.dsc_optc_cfg;
+ struct display_stream_compressor *dsc;
+
+ if (!params)
+ return;
- if (dsc && dsc->funcs->dsc_set_config)
- dsc->funcs->dsc_set_config(dsc, dsc_cfg, dsc_optc_cfg);
+ dsc = params->dsc_set_config_params.dsc;
+
+ if (dsc && dsc->funcs && dsc->funcs->dsc_set_config)
+ dsc->funcs->dsc_set_config(dsc);
}
void hwss_dsc_enable(union block_sequence_params *params)
@@ -3306,24 +3303,18 @@ void hwss_dsc_enable(union block_sequence_params *params)
void hwss_tg_set_dsc_config(union block_sequence_params *params)
{
- struct timing_generator *tg = params->tg_set_dsc_config_params.tg;
- enum optc_dsc_mode optc_dsc_mode = OPTC_DSC_DISABLED;
- uint32_t bytes_per_pixel = 0;
- uint32_t slice_width = 0;
+ struct timing_generator *tg;
- if (params->tg_set_dsc_config_params.enable) {
- struct dsc_optc_config *dsc_optc_cfg = params->tg_set_dsc_config_params.dsc_optc_cfg;
+ if (!params)
+ return;
- if (dsc_optc_cfg) {
- bytes_per_pixel = dsc_optc_cfg->bytes_per_pixel;
- slice_width = dsc_optc_cfg->slice_width;
- optc_dsc_mode = dsc_optc_cfg->is_pixel_format_444 ?
- OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
- }
- }
+ tg = params->tg_set_dsc_config_params.tg;
- if (tg && tg->funcs->set_dsc_config)
- tg->funcs->set_dsc_config(tg, optc_dsc_mode, bytes_per_pixel, slice_width);
+ if (tg && tg->funcs && tg->funcs->set_dsc_config)
+ tg->funcs->set_dsc_config(tg,
+ params->tg_set_dsc_config_params.dsc_mode,
+ params->tg_set_dsc_config_params.bytes_per_pixel,
+ params->tg_set_dsc_config_params.slice_width);
}
void hwss_dsc_disconnect(union block_sequence_params *params)
@@ -3343,41 +3334,6 @@ void hwss_dsc_read_state(union block_sequence_params *params)
dsc->funcs->dsc_read_state(dsc, dsc_state);
}
-void hwss_dsc_calculate_and_set_config(union block_sequence_params *params)
-{
- struct pipe_ctx *pipe_ctx = params->dsc_calculate_and_set_config_params.pipe_ctx;
- struct pipe_ctx *top_pipe = pipe_ctx;
- bool enable = params->dsc_calculate_and_set_config_params.enable;
- int opp_cnt = params->dsc_calculate_and_set_config_params.opp_cnt;
-
- struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
- struct dc_stream_state *stream = pipe_ctx->stream;
-
- if (!dsc || !enable)
- return;
-
- /* Calculate DSC configuration - extracted from dcn32_update_dsc_on_stream */
- struct dsc_config dsc_cfg;
-
- while (top_pipe->prev_odm_pipe)
- top_pipe = top_pipe->prev_odm_pipe;
-
- dsc_cfg.pic_width = (stream->timing.h_addressable + top_pipe->dsc_padding_params.dsc_hactive_padding +
- stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
- dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
- dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
- dsc_cfg.color_depth = stream->timing.display_color_depth;
- dsc_cfg.is_odm = top_pipe->next_odm_pipe ? true : false;
- dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
- dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
- dsc_cfg.dsc_padding = top_pipe->dsc_padding_params.dsc_hactive_padding;
-
- /* Set DSC configuration */
- if (dsc->funcs->dsc_set_config)
- dsc->funcs->dsc_set_config(dsc, &dsc_cfg,
- ¶ms->dsc_calculate_and_set_config_params.dsc_optc_cfg);
-}
-
void hwss_dsc_enable_with_opp(union block_sequence_params *params)
{
struct display_stream_compressor *dsc = params->dsc_enable_with_opp_params.dsc;
@@ -4474,24 +4430,18 @@ void hwss_stream_enc_update_dp_info_packets(union block_sequence_params *params)
void hwss_stream_enc_dp_set_dsc_config(union block_sequence_params *params)
{
- if (params->stream_enc_dp_set_dsc_config_params.stream_enc &&
- params->stream_enc_dp_set_dsc_config_params.stream_enc->funcs->dp_set_dsc_config) {
- enum optc_dsc_mode dsc_mode = OPTC_DSC_DISABLED;
- uint32_t dsc_bytes_per_pixel = 0;
- uint32_t dsc_slice_width = 0;
- const struct dsc_optc_config *dsc_optc_cfg = params->stream_enc_dp_set_dsc_config_params.dsc_optc_cfg;
+ struct stream_encoder *stream_enc;
- if (dsc_optc_cfg) {
- dsc_mode = dsc_optc_cfg->is_pixel_format_444 ?
- OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
- dsc_bytes_per_pixel = dsc_optc_cfg->bytes_per_pixel;
- dsc_slice_width = dsc_optc_cfg->slice_width;
- }
+ if (!params)
+ return;
- params->stream_enc_dp_set_dsc_config_params.stream_enc->funcs->dp_set_dsc_config(
- params->stream_enc_dp_set_dsc_config_params.stream_enc,
- dsc_mode, dsc_bytes_per_pixel, dsc_slice_width);
- }
+ stream_enc = params->stream_enc_dp_set_dsc_config_params.stream_enc;
+
+ if (stream_enc && stream_enc->funcs && stream_enc->funcs->dp_set_dsc_config)
+ stream_enc->funcs->dp_set_dsc_config(stream_enc,
+ params->stream_enc_dp_set_dsc_config_params.dsc_mode,
+ params->stream_enc_dp_set_dsc_config_params.bytes_per_pixel,
+ params->stream_enc_dp_set_dsc_config_params.slice_width);
}
void hwss_hpo_dp_stream_enc_dp_set_dsc_pps_info_packet(union block_sequence_params *params)
@@ -4640,16 +4590,6 @@ void hwss_link_set_dpms_on(union block_sequence_params *params)
pipe_ctx->stream->link->dc->link_srv->set_dpms_on(state, pipe_ctx);
}
-void hwss_dsc_set_config_simple(union block_sequence_params *params)
-{
- struct display_stream_compressor *dsc = params->dsc_set_config_simple_params.dsc;
- struct dsc_config *dsc_cfg = ¶ms->dsc_set_config_simple_params.dsc_cfg;
- struct dsc_optc_config *dsc_optc_cfg = ¶ms->dsc_set_config_simple_params.dsc_optc_cfg;
-
- if (dsc && dsc->funcs && dsc->funcs->dsc_set_config)
- dsc->funcs->dsc_set_config(dsc, dsc_cfg, dsc_optc_cfg);
-}
-
/*
* Clock manager executor functions
*/
@@ -4726,16 +4666,57 @@ void hwss_add_dccg_set_dto_dscclk(struct block_sequence_state *seq_state,
}
}
-void hwss_add_dsc_calculate_and_set_config(struct block_sequence_state *seq_state,
- struct pipe_ctx *pipe_ctx, bool enable, int opp_cnt)
+bool hwss_prepare_dsc_config_for_pipe(
+ struct pipe_ctx *pipe_ctx, int opp_cnt, uint32_t dsc_padding,
+ struct dsc_optc_config *dsc_optc_cfg)
{
- if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
- seq_state->steps[*seq_state->num_steps].func = DSC_CALCULATE_AND_SET_CONFIG;
- seq_state->steps[*seq_state->num_steps].params.dsc_calculate_and_set_config_params.pipe_ctx = pipe_ctx;
- seq_state->steps[*seq_state->num_steps].params.dsc_calculate_and_set_config_params.enable = enable;
- seq_state->steps[*seq_state->num_steps].params.dsc_calculate_and_set_config_params.opp_cnt = opp_cnt;
- (*seq_state->num_steps)++;
- }
+ struct dsc_config dsc_cfg = {};
+ struct dsc_optc_config optc = {};
+ struct display_stream_compressor *dsc;
+ struct pipe_ctx *top_pipe = pipe_ctx;
+ struct dc_stream_state *stream;
+ bool is_config_ok;
+
+ if (dsc_optc_cfg)
+ memset(dsc_optc_cfg, 0, sizeof(*dsc_optc_cfg));
+
+ if (!pipe_ctx || !pipe_ctx->stream || !pipe_ctx->stream_res.dsc ||
+ opp_cnt <= 0 || opp_cnt > MAX_PIPES)
+ return false;
+
+ dsc = pipe_ctx->stream_res.dsc;
+
+ if (!dsc->funcs || !dsc->funcs->dsc_prepare_config || !dsc->funcs->dsc_set_config)
+ return false;
+
+ stream = pipe_ctx->stream;
+
+ if (!stream->timing.dsc_cfg.num_slices_h ||
+ stream->timing.dsc_cfg.num_slices_h % opp_cnt)
+ return false;
+
+ while (top_pipe->prev_odm_pipe)
+ top_pipe = top_pipe->prev_odm_pipe;
+
+ dsc_cfg.pic_width =
+ (stream->timing.h_addressable + top_pipe->dsc_padding_params.dsc_hactive_padding +
+ stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
+ dsc_cfg.pic_height = stream->timing.v_addressable +
+ stream->timing.v_border_top + stream->timing.v_border_bottom;
+ dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
+ dsc_cfg.color_depth = stream->timing.display_color_depth;
+ dsc_cfg.is_odm = top_pipe->next_odm_pipe ? true : false;
+ dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
+ dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
+ dsc_cfg.dsc_padding = dsc_padding;
+
+ is_config_ok = dsc->funcs->dsc_prepare_config(dsc, &dsc_cfg, &optc);
+ ASSERT(is_config_ok);
+ if (!is_config_ok)
+ return false;
+ if (dsc_optc_cfg)
+ *dsc_optc_cfg = optc;
+ return true;
}
void hwss_add_mpc_remove_mpcc(struct block_sequence_state *seq_state,
@@ -4777,13 +4758,28 @@ void hwss_add_dsc_enable_with_opp(struct block_sequence_state *seq_state,
}
void hwss_add_tg_set_dsc_config(struct block_sequence_state *seq_state,
- struct timing_generator *tg, struct dsc_optc_config *dsc_optc_cfg, bool enable)
+ struct timing_generator *tg, const struct dsc_optc_config *dsc_optc_cfg, bool enable)
{
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps ||
+ !tg || !tg->funcs || !tg->funcs->set_dsc_config || (enable && !dsc_optc_cfg))
+ return;
+
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+ struct tg_set_dsc_config_params *p =
+ &seq_state->steps[*seq_state->num_steps].params.tg_set_dsc_config_params;
+
seq_state->steps[*seq_state->num_steps].func = TG_SET_DSC_CONFIG;
- seq_state->steps[*seq_state->num_steps].params.tg_set_dsc_config_params.tg = tg;
- seq_state->steps[*seq_state->num_steps].params.tg_set_dsc_config_params.dsc_optc_cfg = dsc_optc_cfg;
- seq_state->steps[*seq_state->num_steps].params.tg_set_dsc_config_params.enable = enable;
+ p->tg = tg;
+ p->dsc_mode = OPTC_DSC_DISABLED;
+ p->bytes_per_pixel = 0;
+ p->slice_width = 0;
+
+ if (enable && dsc_optc_cfg) {
+ p->dsc_mode = dsc_optc_cfg->is_pixel_format_444 ?
+ OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
+ p->bytes_per_pixel = dsc_optc_cfg->bytes_per_pixel;
+ p->slice_width = dsc_optc_cfg->slice_width;
+ }
(*seq_state->num_steps)++;
}
}
@@ -6106,28 +6102,157 @@ void hwss_add_stream_enc_update_dp_info_packets(struct block_sequence_state *seq
}
}
-void hwss_add_dsc_set_config(struct block_sequence_state *seq_state,
- struct display_stream_compressor *dsc,
- const struct dsc_config *dsc_cfg,
- const struct dsc_optc_config *dsc_optc_cfg)
+bool hwss_add_dsc_set_config(struct block_sequence_state *seq_state,
+ struct display_stream_compressor *dsc)
{
- if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
- seq_state->steps[*seq_state->num_steps].func = DSC_SET_CONFIG_SIMPLE;
- seq_state->steps[*seq_state->num_steps].params.dsc_set_config_simple_params.dsc = dsc;
- seq_state->steps[*seq_state->num_steps].params.dsc_set_config_simple_params.dsc_cfg = *dsc_cfg;
- seq_state->steps[*seq_state->num_steps].params.dsc_set_config_simple_params.dsc_optc_cfg = *dsc_optc_cfg;
- (*seq_state->num_steps)++;
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps ||
+ *seq_state->num_steps >= MAX_HWSS_BLOCK_SEQUENCE_SIZE ||
+ !dsc || !dsc->funcs || !dsc->funcs->dsc_set_config)
+ return false;
+ seq_state->steps[*seq_state->num_steps].func = DSC_SET_CONFIG;
+ seq_state->steps[*seq_state->num_steps].params.dsc_set_config_params.dsc = dsc;
+ (*seq_state->num_steps)++;
+ return true;
+}
+
+bool hwss_add_dsc_sequence_for_pipe(struct block_sequence_state *seq_state,
+ struct pipe_ctx *pipe_ctx, int opp_cnt, uint32_t dsc_padding,
+ struct dsc_optc_config *dsc_optc_cfg)
+{
+ if (dsc_optc_cfg)
+ memset(dsc_optc_cfg, 0, sizeof(*dsc_optc_cfg));
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps ||
+ *seq_state->num_steps > MAX_HWSS_BLOCK_SEQUENCE_SIZE - 2 ||
+ !pipe_ctx || !pipe_ctx->stream_res.opp || !pipe_ctx->stream_res.dsc ||
+ !pipe_ctx->stream_res.dsc->funcs || !pipe_ctx->stream_res.dsc->funcs->dsc_enable)
+ return false;
+
+ if (!hwss_prepare_dsc_config_for_pipe(pipe_ctx, opp_cnt, dsc_padding, dsc_optc_cfg))
+ return false;
+
+ if (!hwss_add_dsc_set_config(seq_state, pipe_ctx->stream_res.dsc))
+ return false;
+
+ hwss_add_dsc_enable_with_opp(seq_state, pipe_ctx);
+ return true;
+}
+
+bool hwss_add_dsc_sequence_for_stream(struct block_sequence_state *seq_state,
+ struct pipe_ctx *pipe_ctx, uint32_t dsc_padding,
+ struct dsc_optc_config *dsc_optc_cfg)
+{
+ struct pipe_ctx *top_pipe = pipe_ctx;
+ struct pipe_ctx *odm_pipe;
+ struct dc_stream_state *stream;
+ struct display_stream_compressor *dsc;
+ struct dccg *dccg = NULL;
+ struct dsc_optc_config optc = {};
+ int opp_cnt = 0;
+ int num_slices_h;
+ unsigned int initial_steps;
+ unsigned int required_steps;
+ bool should_use_dto_dscclk = false;
+
+ if (dsc_optc_cfg)
+ memset(dsc_optc_cfg, 0, sizeof(*dsc_optc_cfg));
+
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps || !top_pipe ||
+ *seq_state->num_steps > MAX_HWSS_BLOCK_SEQUENCE_SIZE)
+ return false;
+
+ while (top_pipe->prev_odm_pipe)
+ top_pipe = top_pipe->prev_odm_pipe;
+
+ if (!top_pipe->stream || !top_pipe->stream->timing.flags.DSC ||
+ !top_pipe->stream_res.tg || !top_pipe->stream_res.tg->funcs ||
+ !top_pipe->stream_res.tg->funcs->set_dsc_config)
+ return false;
+
+ dsc = top_pipe->stream_res.dsc;
+ stream = top_pipe->stream;
+
+ if (stream->ctx && stream->ctx->dc && stream->ctx->dc->res_pool)
+ dccg = stream->ctx->dc->res_pool->dccg;
+
+ for (odm_pipe = top_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
+
+ if (++opp_cnt > MAX_PIPES || odm_pipe->stream != stream ||
+ !odm_pipe->stream_res.opp || !odm_dsc || !odm_dsc->funcs ||
+ !odm_dsc->funcs->dsc_prepare_config || !odm_dsc->funcs->dsc_set_config ||
+ !odm_dsc->funcs->dsc_enable)
+ return false;
}
+
+ if (!stream->timing.dsc_cfg.num_slices_h || stream->timing.dsc_cfg.num_slices_h % opp_cnt)
+ return false;
+ num_slices_h = stream->timing.dsc_cfg.num_slices_h / opp_cnt;
+
+ if (dccg && dccg->funcs && dccg->funcs->set_dto_dscclk &&
+ stream->timing.pix_clk_100hz > 480000)
+ should_use_dto_dscclk = true;
+
+ initial_steps = *seq_state->num_steps;
+ required_steps = opp_cnt * (should_use_dto_dscclk ? 3 : 2) + 1;
+ if (required_steps > MAX_HWSS_BLOCK_SEQUENCE_SIZE - initial_steps)
+ return false;
+
+ /* Step 1: Set DTO DSCCLK for master DSC if needed */
+ if (should_use_dto_dscclk)
+ hwss_add_dccg_set_dto_dscclk(seq_state, dccg, dsc->inst, num_slices_h);
+
+ /* Step 2: Configure and enable master DSC + OPP */
+ if (!hwss_add_dsc_sequence_for_pipe(seq_state, top_pipe, opp_cnt, dsc_padding, &optc))
+ goto fail;
+
+ /* Step 3: Configure and enable ODM DSC blocks + OPP */
+ for (odm_pipe = top_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
+
+ if (should_use_dto_dscclk)
+ hwss_add_dccg_set_dto_dscclk(seq_state, dccg, odm_dsc->inst, num_slices_h);
+
+ if (!hwss_add_dsc_sequence_for_pipe(seq_state, odm_pipe, opp_cnt, dsc_padding, NULL))
+ goto fail;
+ }
+
+ /* Step 4: Configure DSC in timing generator (OPTC) */
+ hwss_add_tg_set_dsc_config(seq_state, top_pipe->stream_res.tg, &optc, true);
+
+ if (dsc_optc_cfg)
+ *dsc_optc_cfg = optc;
+
+ return true;
+
+fail:
+ *seq_state->num_steps = initial_steps;
+ return false;
}
void hwss_add_stream_enc_dp_set_dsc_config(struct block_sequence_state *seq_state,
struct stream_encoder *stream_enc,
const struct dsc_optc_config *dsc_optc_cfg)
{
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps ||
+ !stream_enc || !stream_enc->funcs || !stream_enc->funcs->dp_set_dsc_config)
+ return;
+
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+ struct stream_enc_dp_set_dsc_config_params *p =
+ &seq_state->steps[*seq_state->num_steps].params.stream_enc_dp_set_dsc_config_params;
+
seq_state->steps[*seq_state->num_steps].func = STREAM_ENC_DP_SET_DSC_CONFIG;
- seq_state->steps[*seq_state->num_steps].params.stream_enc_dp_set_dsc_config_params.stream_enc = stream_enc;
- seq_state->steps[*seq_state->num_steps].params.stream_enc_dp_set_dsc_config_params.dsc_optc_cfg = dsc_optc_cfg;
+ p->stream_enc = stream_enc;
+ p->dsc_mode = OPTC_DSC_DISABLED;
+ p->bytes_per_pixel = 0;
+ p->slice_width = 0;
+
+ if (dsc_optc_cfg) {
+ p->dsc_mode = dsc_optc_cfg->is_pixel_format_444 ?
+ OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
+ p->bytes_per_pixel = dsc_optc_cfg->bytes_per_pixel;
+ p->slice_width = dsc_optc_cfg->slice_width;
+ }
(*seq_state->num_steps)++;
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
index cede9588bad8..9c90cceee136 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c
@@ -30,13 +30,14 @@
#include "dsc/dscc_types.h"
#include "dsc/rc_calc.h"
-static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals);
+static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc20_reg_values *reg_vals);
static const struct dsc_funcs dcn20_dsc_funcs = {
.dsc_get_enc_caps = dsc2_get_enc_caps,
.dsc_read_state = dsc2_read_state,
.dsc_read_reg_state = dsc2_read_reg_state,
.dsc_validate_stream = dsc2_validate_stream,
+ .dsc_prepare_config = dsc2_prepare_config,
.dsc_set_config = dsc2_set_config,
.dsc_get_packed_pps = dsc2_get_packed_pps,
.dsc_enable = dsc2_enable,
@@ -188,26 +189,41 @@ void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_conf
DC_LOG_DSC("\tcolor_depth %d", config->color_depth);
}
-void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+bool dsc2_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg)
{
- bool is_config_ok;
- struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
+ struct dcn20_dsc *dsc20;
+ struct dsc20_reg_values reg_vals = {};
+ struct dsc_optc_config optc = {};
- DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst);
- dsc_config_log(dsc, dsc_cfg);
- is_config_ok = dsc_prepare_config(dsc_cfg, &dsc20->reg_vals, dsc_optc_cfg);
- ASSERT(is_config_ok);
+ if (!dsc || !dsc_cfg || !dsc_optc_cfg)
+ return false;
+
+ dsc20 = TO_DCN20_DSC(dsc);
+ if (!dsc_prepare_config(dsc_cfg, ®_vals, &optc))
+ return false;
+ dsc20->reg_vals = reg_vals;
+ *dsc_optc_cfg = optc;
+ return true;
+}
+
+void dsc2_set_config(struct display_stream_compressor *dsc)
+{
+ struct dcn20_dsc *dsc20;
+
+ if (!dsc)
+ return;
+
+ dsc20 = TO_DCN20_DSC(dsc);
DC_LOG_DSC("programming DSC Picture Parameter Set (PPS):");
dsc_log_pps(dsc, &dsc20->reg_vals.pps);
dsc_write_to_registers(dsc, &dsc20->reg_vals);
}
-
bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps)
{
bool is_config_ok;
- struct dsc_reg_values dsc_reg_vals;
+ struct dsc20_reg_values dsc_reg_vals;
struct dsc_optc_config dsc_optc_cfg;
memset(&dsc_reg_vals, 0, sizeof(dsc_reg_vals));
@@ -368,7 +384,7 @@ void dsc_override_rc_params(struct rc_params *rc, const struct dc_dsc_rc_params_
rc->flatness_det_thresh = override->flatness_det_thresh;
}
-bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals,
+bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc20_reg_values *dsc_reg_vals,
struct dsc_optc_config *dsc_optc_cfg)
{
struct dsc_parameters dsc_params;
@@ -515,11 +531,11 @@ enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_dep
}
-void dsc_init_reg_values(struct dsc_reg_values *reg_vals)
+void dsc_init_reg_values(struct dsc20_reg_values *reg_vals)
{
int i;
- memset(reg_vals, 0, sizeof(struct dsc_reg_values));
+ memset(reg_vals, 0, sizeof(struct dsc20_reg_values));
/* Non-PPS values */
reg_vals->dsc_clock_enable = 1;
@@ -567,11 +583,11 @@ void dsc_init_reg_values(struct dsc_reg_values *reg_vals)
reg_vals->pps.rc_tgt_offset_high = 3;
}
-/* Updates dsc_reg_values::reg_vals::xxx fields based on the values from computed params.
+/* Updates dsc20_reg_values::reg_vals::xxx fields based on the values from computed params.
* This is required because dscc_compute_dsc_parameters returns a modified PPS, which in turn
* affects non-PPS register values.
*/
-void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params)
+void dsc_update_from_dsc_parameters(struct dsc20_reg_values *reg_vals, const struct dsc_parameters *dsc_params)
{
int i;
@@ -584,7 +600,7 @@ void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struc
reg_vals->rc_buffer_model_size = dsc_params->rc_buffer_model_size;
}
-static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals)
+static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc20_reg_values *reg_vals)
{
uint32_t temp_int;
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h
index 2337c3a97235..28fa02b0d6ce 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h
@@ -536,7 +536,7 @@ enum dsc_pixel_format {
DSC_PIXFMT_UNKNOWN
};
-struct dsc_reg_values {
+struct dsc20_reg_values {
/* PPS registers */
struct drm_dsc_config pps;
@@ -564,7 +564,7 @@ struct dcn20_dsc {
const struct dcn20_dsc_shift *dsc_shift;
const struct dcn20_dsc_mask *dsc_mask;
- struct dsc_reg_values reg_vals;
+ struct dsc20_reg_values reg_vals;
int max_image_width;
};
@@ -579,7 +579,7 @@ void dsc_override_rc_params(struct rc_params *rc,
const struct dc_dsc_rc_params_override *override);
bool dsc_prepare_config(const struct dsc_config *dsc_cfg,
- struct dsc_reg_values *dsc_reg_vals,
+ struct dsc20_reg_values *dsc_reg_vals,
struct dsc_optc_config *dsc_optc_cfg);
enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc,
@@ -587,9 +587,9 @@ enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_en
enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth);
-void dsc_init_reg_values(struct dsc_reg_values *reg_vals);
+void dsc_init_reg_values(struct dsc20_reg_values *reg_vals);
-void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params);
+void dsc_update_from_dsc_parameters(struct dsc20_reg_values *reg_vals, const struct dsc_parameters *dsc_params);
void dsc2_construct(struct dcn20_dsc *dsc,
struct dc_context *ctx,
@@ -608,8 +608,9 @@ bool dsc2_get_packed_pps(struct display_stream_compressor *dsc,
void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
void dsc2_read_reg_state(struct display_stream_compressor *dsc, struct dcn_dsc_reg_state *dccg_reg_state);
bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
-void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+bool dsc2_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg);
+void dsc2_set_config(struct display_stream_compressor *dsc);
void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
void dsc2_disable(struct display_stream_compressor *dsc);
void dsc2_disconnect(struct display_stream_compressor *dsc);
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c
index d84c3399d386..fa0851b528d6 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c
@@ -34,6 +34,7 @@ static const struct dsc_funcs dcn35_dsc_funcs = {
.dsc_read_state = dsc2_read_state,
.dsc_read_reg_state = dsc2_read_reg_state,
.dsc_validate_stream = dsc2_validate_stream,
+ .dsc_prepare_config = dsc2_prepare_config,
.dsc_set_config = dsc2_set_config,
.dsc_get_packed_pps = dsc2_get_packed_pps,
.dsc_enable = dsc35_enable,
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
index 749547960046..bd5467594803 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
@@ -9,7 +9,7 @@
#include "dsc/dscc_types.h"
#include "dsc/rc_calc.h"
-static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals);
+static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc20_reg_values *reg_vals);
/* Object I/F functions */
//static void dsc401_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz);
@@ -19,6 +19,7 @@ static void dsc401_get_single_enc_caps(struct dsc_enc_caps *dsc_enc_caps, unsign
static const struct dsc_funcs dcn401_dsc_funcs = {
.dsc_read_state = dsc401_read_state,
.dsc_validate_stream = dsc401_validate_stream,
+ .dsc_prepare_config = dsc401_prepare_config,
.dsc_set_config = dsc401_set_config,
.dsc_get_packed_pps = dsc2_get_packed_pps,
.dsc_enable = dsc401_enable,
@@ -127,16 +128,31 @@ bool dsc401_validate_stream(struct display_stream_compressor *dsc, const struct
return dsc_prepare_config(dsc_cfg, &dsc401->reg_vals, &dsc_optc_cfg);
}
-void dsc401_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+bool dsc401_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg)
{
- bool is_config_ok;
- struct dcn401_dsc *dsc401 = TO_DCN401_DSC(dsc);
+ struct dcn401_dsc *dsc401;
+ struct dsc20_reg_values reg_vals = {};
+ struct dsc_optc_config optc = {};
+
+ if (!dsc || !dsc_cfg || !dsc_optc_cfg)
+ return false;
+
+ dsc401 = TO_DCN401_DSC(dsc);
+ if (!dsc_prepare_config(dsc_cfg, ®_vals, &optc))
+ return false;
+ dsc401->reg_vals = reg_vals;
+ *dsc_optc_cfg = optc;
+ return true;
+}
+
+void dsc401_set_config(struct display_stream_compressor *dsc)
+{
+ struct dcn401_dsc *dsc401;
- DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst);
- dsc_config_log(dsc, dsc_cfg);
- is_config_ok = dsc_prepare_config(dsc_cfg, &dsc401->reg_vals, dsc_optc_cfg);
- ASSERT(is_config_ok);
+ if (!dsc)
+ return;
+ dsc401 = TO_DCN401_DSC(dsc);
DC_LOG_DSC("programming DSC Picture Parameter Set (PPS):");
dsc_log_pps(dsc, &dsc401->reg_vals.pps);
dsc_write_to_registers(dsc, &dsc401->reg_vals);
@@ -203,7 +219,7 @@ void dsc401_disconnect(struct display_stream_compressor *dsc)
DSCRM_DSC_FORWARD_EN, 0);
}
-static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals)
+static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc20_reg_values *reg_vals)
{
uint32_t temp_int;
struct dcn401_dsc *dsc401 = TO_DCN401_DSC(dsc);
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h
index 7acd57eb4f42..d1c51454d5b6 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.h
@@ -320,7 +320,7 @@ struct dcn401_dsc {
const struct dcn401_dsc_shift *dsc_shift;
const struct dcn401_dsc_mask *dsc_mask;
- struct dsc_reg_values reg_vals;
+ struct dsc20_reg_values reg_vals;
int max_image_width;
};
@@ -336,8 +336,9 @@ void dsc401_set_fgcg(struct dcn401_dsc *dsc401, bool enable);
void dsc401_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
bool dsc401_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
-void dsc401_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+bool dsc401_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg);
+void dsc401_set_config(struct display_stream_compressor *dsc);
void dsc401_enable(struct display_stream_compressor *dsc, int opp_pipe);
void dsc401_disable(struct display_stream_compressor *dsc);
void dsc401_disconnect(struct display_stream_compressor *dsc);
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c
index 5bb4ed1d1ba7..91ec525b11d0 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c
@@ -12,6 +12,7 @@
static const struct dsc_funcs dcn60_dsc_funcs = {
.dsc_read_state = dsc401_read_state,
.dsc_validate_stream = dsc401_validate_stream,
+ .dsc_prepare_config = dsc60_prepare_config,
.dsc_set_config = dsc60_set_config,
.dsc_get_packed_pps = dsc2_get_packed_pps,
.dsc_enable = dsc401_enable,
@@ -115,10 +116,10 @@ static void dsc60_init_reg_values(struct dsc60_reg_values *reg_vals)
reg_vals->pps.rc_tgt_offset_high = 3;
}
-/*Updates dsc_reg_values::reg_vals::xxx fields based on the values from computed params.
-* This is required because dscc_compute_dsc_parameters returns a modified PPS, which in turn
-* affects non - PPS register values.
-*/
+/* Updates dsc60_reg_values::reg_vals::xxx fields based on the values from computed params.
+ * This is required because dscc_compute_dsc_parameters returns a modified PPS, which in turn
+ * affects non-PPS register values.
+ */
static void dsc60_update_from_dsc_parameters(struct dsc60_reg_values *reg_vals, const struct dsc_parameters *dsc_params)
{
int i;
@@ -132,7 +133,7 @@ static void dsc60_update_from_dsc_parameters(struct dsc60_reg_values *reg_vals,
reg_vals->rc_buffer_model_size = dsc_params->rc_buffer_model_size;
}
-static bool dsc60_prepare_config(const struct dsc_config *dsc_cfg, struct dsc60_reg_values *dsc_reg_vals,
+static bool dsc60_prepare_config_internal(const struct dsc_config *dsc_cfg, struct dsc60_reg_values *dsc_reg_vals,
struct dsc_optc_config *dsc_optc_cfg)
{
struct dsc_parameters dsc_params;
@@ -403,16 +404,32 @@ static void dsc60_write_to_registers(struct display_stream_compressor *dsc, cons
}
-void dsc60_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+bool dsc60_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg)
{
- bool is_config_ok;
- struct dcn60_dsc *dsc60 = TO_DCN60_DSC(dsc);
+ struct dcn60_dsc *dsc60;
+ struct dsc60_reg_values reg_vals = {};
+ struct dsc_optc_config optc = {};
+
+ if (!dsc || !dsc_cfg || !dsc_optc_cfg)
+ return false;
+
+ dsc60 = TO_DCN60_DSC(dsc);
+ if (!dsc60_prepare_config_internal(dsc_cfg, ®_vals, &optc))
+ return false;
+ dsc60->reg_vals = reg_vals;
+ *dsc_optc_cfg = optc;
+ return true;
+}
+
+void dsc60_set_config(struct display_stream_compressor *dsc)
+{
+ struct dcn60_dsc *dsc60;
+
+ if (!dsc)
+ return;
- DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst);
- dsc_config_log(dsc, dsc_cfg);
- is_config_ok = dsc60_prepare_config(dsc_cfg, &dsc60->reg_vals, dsc_optc_cfg);
- ASSERT(is_config_ok);
+ dsc60 = TO_DCN60_DSC(dsc);
DC_LOG_DSC("programming DSC Picture Parameter Set (PPS):");
dsc_log_pps(dsc, &dsc60->reg_vals.pps);
dsc60_write_to_registers(dsc, &dsc60->reg_vals);
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h
index b7f2d8031121..a1a3a139cd3b 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h
@@ -239,8 +239,9 @@ void dsc60_construct(struct dcn60_dsc *dsc,
const struct dcn60_dsc_mask *dsc_mask);
void dsc60_set_fgcg(struct display_stream_compressor *dsc, bool enable);
-void dsc60_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+bool dsc60_prepare_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg);
+void dsc60_set_config(struct display_stream_compressor *dsc);
void dsc60_get_single_enc_caps(struct dsc_enc_caps *dsc_enc_caps, unsigned int max_dscclk_khz);
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
index ab37a7eaaf01..cb7b0b1d8686 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
@@ -116,8 +116,9 @@ struct dsc_funcs {
void (*dsc_read_state)(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
void (*dsc_read_reg_state)(struct display_stream_compressor *dsc, struct dcn_dsc_reg_state *dccg_reg_state);
bool (*dsc_validate_stream)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
- void (*dsc_set_config)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
+ bool (*dsc_prepare_config)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
struct dsc_optc_config *dsc_optc_cfg);
+ void (*dsc_set_config)(struct display_stream_compressor *dsc);
bool (*dsc_get_packed_pps)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
uint8_t *dsc_packed_pps);
void (*dsc_enable)(struct display_stream_compressor *dsc, int opp_pipe);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
index 56d41c6fa3ee..93d8483d6f80 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
@@ -110,13 +110,23 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
dsc_cfg.dsc_padding = 0;
- dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
+ if (!dsc->funcs->dsc_prepare_config(dsc, &dsc_cfg, &dsc_optc_cfg)) {
+ ASSERT(false);
+ return;
+ }
+ dsc->funcs->dsc_set_config(dsc);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
ASSERT(odm_dsc);
- odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
+ if (!odm_dsc)
+ return;
+ if (!odm_dsc->funcs->dsc_prepare_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg)) {
+ ASSERT(false);
+ return;
+ }
+ odm_dsc->funcs->dsc_set_config(odm_dsc);
odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
}
dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index 10361f3b6122..e7bf865755d4 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -1103,17 +1103,25 @@ void dcn32_update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, dsc->inst, dsc_cfg.dc_dsc_cfg.num_slices_h);
- dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
+ if (!dsc->funcs->dsc_prepare_config(dsc, &dsc_cfg, &dsc_optc_cfg)) {
+ ASSERT(false);
+ return;
+ }
+ dsc->funcs->dsc_set_config(dsc);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
ASSERT(odm_dsc);
if (!odm_dsc)
- continue;
+ return;
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst, dsc_cfg.dc_dsc_cfg.num_slices_h);
- odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
+ if (!odm_dsc->funcs->dsc_prepare_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg)) {
+ ASSERT(false);
+ return;
+ }
+ odm_dsc->funcs->dsc_set_config(odm_dsc);
odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
}
optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index f2bf7d1ca4f7..23c09801f12f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -369,13 +369,23 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
dsc_cfg.dsc_padding = 0;
- dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
+ if (!dsc->funcs->dsc_prepare_config(dsc, &dsc_cfg, &dsc_optc_cfg)) {
+ ASSERT(false);
+ return;
+ }
+ dsc->funcs->dsc_set_config(dsc);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
ASSERT(odm_dsc);
- odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
+ if (!odm_dsc)
+ return;
+ if (!odm_dsc->funcs->dsc_prepare_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg)) {
+ ASSERT(false);
+ return;
+ }
+ odm_dsc->funcs->dsc_set_config(odm_dsc);
odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
}
dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 379902bdef0a..0abdfc55290c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -1779,54 +1779,11 @@ static void dcn401_add_dsc_sequence_for_odm_change(struct dc *dc, struct dc_stat
/* Process new DSC configuration if DSC is enabled */
if (otg_master->stream_res.dsc && otg_master->stream->timing.flags.DSC) {
- struct dc_stream_state *stream = otg_master->stream;
- struct pipe_ctx *odm_pipe;
- int opp_cnt = 1;
- int last_dsc_calc = 0;
- bool should_use_dto_dscclk = (dc->res_pool->dccg->funcs->set_dto_dscclk != NULL) &&
- stream->timing.pix_clk_100hz > 480000;
-
- /* Count ODM pipes */
- for (odm_pipe = otg_master->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
- opp_cnt++;
-
- int num_slices_h = stream->timing.dsc_cfg.num_slices_h / opp_cnt;
-
- /* Step 1: Set DTO DSCCLK for main DSC if needed */
- if (should_use_dto_dscclk) {
- hwss_add_dccg_set_dto_dscclk(seq_state, dc->res_pool->dccg,
- otg_master->stream_res.dsc->inst, num_slices_h);
- }
-
- /* Step 2: Calculate and set DSC config for main DSC */
- last_dsc_calc = *seq_state->num_steps;
- hwss_add_dsc_calculate_and_set_config(seq_state, otg_master, true, opp_cnt);
-
- /* Step 3: Enable main DSC block */
- hwss_add_dsc_enable_with_opp(seq_state, otg_master);
-
- /* Step 4: Configure and enable ODM DSC blocks */
- for (odm_pipe = otg_master->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
- if (!odm_pipe->stream_res.dsc)
- continue;
-
- /* Set DTO DSCCLK for ODM DSC if needed */
- if (should_use_dto_dscclk) {
- hwss_add_dccg_set_dto_dscclk(seq_state, dc->res_pool->dccg,
- odm_pipe->stream_res.dsc->inst, num_slices_h);
- }
-
- /* Calculate and set DSC config for ODM DSC */
- last_dsc_calc = *seq_state->num_steps;
- hwss_add_dsc_calculate_and_set_config(seq_state, odm_pipe, true, opp_cnt);
-
- /* Enable ODM DSC block */
- hwss_add_dsc_enable_with_opp(seq_state, odm_pipe);
+ if (!hwss_add_dsc_sequence_for_stream(seq_state, otg_master,
+ otg_master->dsc_padding_params.dsc_hactive_padding, NULL)) {
+ ASSERT(false);
+ return;
}
-
- /* Step 5: Configure DSC in timing generator */
- hwss_add_tg_set_dsc_config(seq_state, otg_master->stream_res.tg,
- &seq_state->steps[last_dsc_calc].params.dsc_calculate_and_set_config_params.dsc_optc_cfg, true);
} else if (otg_master->stream_res.dsc && !otg_master->stream->timing.flags.DSC) {
/* Disable DSC in OPTC */
hwss_add_tg_set_dsc_config(seq_state, otg_master->stream_res.tg, NULL, false);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index a1b994edf80a..7800b0501c39 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -279,8 +279,6 @@ struct dccg_set_dto_dscclk_params {
struct dsc_set_config_params {
struct display_stream_compressor *dsc;
- struct dsc_config *dsc_cfg;
- struct dsc_optc_config *dsc_optc_cfg;
};
struct dsc_enable_params {
@@ -290,8 +288,9 @@ struct dsc_enable_params {
struct tg_set_dsc_config_params {
struct timing_generator *tg;
- struct dsc_optc_config *dsc_optc_cfg;
- bool enable;
+ enum optc_dsc_mode dsc_mode;
+ uint32_t bytes_per_pixel;
+ uint32_t slice_width;
};
struct dsc_disconnect_params {
@@ -303,13 +302,6 @@ struct dsc_read_state_params {
struct dcn_dsc_state *dsc_state;
};
-struct dsc_calculate_and_set_config_params {
- struct pipe_ctx *pipe_ctx;
- struct dsc_optc_config dsc_optc_cfg;
- bool enable;
- int opp_cnt;
-};
-
struct dsc_enable_with_opp_params {
struct display_stream_compressor *dsc;
int opp_inst;
@@ -936,15 +928,11 @@ struct stream_enc_update_dp_info_packets_params {
struct pipe_ctx *pipe_ctx;
};
-struct dsc_set_config_simple_params {
- struct display_stream_compressor *dsc;
- struct dsc_config dsc_cfg;
- struct dsc_optc_config dsc_optc_cfg;
-};
-
struct stream_enc_dp_set_dsc_config_params {
struct stream_encoder *stream_enc;
- const struct dsc_optc_config *dsc_optc_cfg;
+ enum optc_dsc_mode dsc_mode;
+ uint32_t bytes_per_pixel;
+ uint32_t slice_width;
};
struct hpo_dp_stream_enc_dp_set_dsc_pps_info_packet_params {
@@ -1084,7 +1072,6 @@ union block_sequence_params {
struct tg_set_dsc_config_params tg_set_dsc_config_params;
struct dsc_disconnect_params dsc_disconnect_params;
struct dsc_read_state_params dsc_read_state_params;
- struct dsc_calculate_and_set_config_params dsc_calculate_and_set_config_params;
struct dsc_enable_with_opp_params dsc_enable_with_opp_params;
struct program_tg_params program_tg_params;
struct tg_program_global_sync_params tg_program_global_sync_params;
@@ -1194,7 +1181,6 @@ union block_sequence_params {
struct hpo_dp_stream_enc_update_dp_info_packets_params hpo_dp_stream_enc_update_dp_info_packets_params;
struct stream_enc_update_dp_info_packets_sdp_line_num_params stream_enc_update_dp_info_packets_sdp_line_num_params;
struct stream_enc_update_dp_info_packets_params stream_enc_update_dp_info_packets_params;
- struct dsc_set_config_simple_params dsc_set_config_simple_params;
struct stream_enc_dp_set_dsc_config_params stream_enc_dp_set_dsc_config_params;
struct hpo_dp_stream_enc_dp_set_dsc_pps_info_packet_params hpo_dp_stream_enc_dp_set_dsc_pps_info_packet_params;
struct stream_enc_dp_set_dsc_pps_info_packet_params stream_enc_dp_set_dsc_pps_info_packet_params;
@@ -1259,7 +1245,6 @@ enum block_sequence_func {
TG_SET_DSC_CONFIG,
DSC_DISCONNECT,
DSC_READ_STATE,
- DSC_CALCULATE_AND_SET_CONFIG,
DSC_ENABLE_WITH_OPP,
TG_PROGRAM_GLOBAL_SYNC,
TG_WAIT_FOR_STATE,
@@ -1350,7 +1335,6 @@ enum block_sequence_func {
HPO_DP_STREAM_ENC_UPDATE_DP_INFO_PACKETS,
STREAM_ENC_UPDATE_DP_INFO_PACKETS_SDP_LINE_NUM,
STREAM_ENC_UPDATE_DP_INFO_PACKETS,
- DSC_SET_CONFIG_SIMPLE,
STREAM_ENC_DP_SET_DSC_CONFIG,
HPO_DP_STREAM_ENC_DP_SET_DSC_PPS_INFO_PACKET,
STREAM_ENC_DP_SET_DSC_PPS_INFO_PACKET,
@@ -1900,12 +1884,8 @@ void hwss_dsc_disconnect(union block_sequence_params *params);
void hwss_dsc_read_state(union block_sequence_params *params);
-void hwss_dsc_calculate_and_set_config(union block_sequence_params *params);
-
void hwss_dsc_enable_with_opp(union block_sequence_params *params);
-void hwss_dsc_set_config_simple(union block_sequence_params *params);
-
void hwss_stream_enc_update_hdmi_info_packets(union block_sequence_params *params);
void hwss_hpo_frl_stream_enc_update_hdmi_info_packets(union block_sequence_params *params);
@@ -2284,8 +2264,9 @@ void hwss_add_tg_wait_double_buffer_pending(struct block_sequence_state *seq_sta
void hwss_add_dccg_set_dto_dscclk(struct block_sequence_state *seq_state,
struct dccg *dccg, int inst, int num_slices_h);
-void hwss_add_dsc_calculate_and_set_config(struct block_sequence_state *seq_state,
- struct pipe_ctx *pipe_ctx, bool enable, int opp_cnt);
+/* Resolves DSC geometry and driver state for pipe; pass NULL if the caller does not need OPTC parameters. */
+bool hwss_prepare_dsc_config_for_pipe(struct pipe_ctx *pipe_ctx, int opp_cnt, uint32_t dsc_padding,
+ struct dsc_optc_config *dsc_optc_cfg);
void hwss_add_mpc_remove_mpcc(struct block_sequence_state *seq_state,
struct mpc *mpc, struct mpc_tree *mpc_tree_params, struct mpcc *mpcc_to_remove);
@@ -2641,7 +2622,7 @@ void hwss_add_hubbub_apply_dedcn21_147_wa(struct block_sequence_state *seq_state
void hwss_add_tg_set_dsc_config(struct block_sequence_state *seq_state,
struct timing_generator *tg,
- struct dsc_optc_config *dsc_optc_cfg,
+ const struct dsc_optc_config *dsc_optc_cfg,
bool enable);
void hwss_add_opp_program_left_edge_extra_pixel(struct block_sequence_state *seq_state,
@@ -2694,10 +2675,18 @@ void hwss_add_stream_enc_update_dp_info_packets_sdp_line_num(struct block_sequen
void hwss_add_stream_enc_update_dp_info_packets(struct block_sequence_state *seq_state,
struct pipe_ctx *pipe_ctx);
-void hwss_add_dsc_set_config(struct block_sequence_state *seq_state,
- struct display_stream_compressor *dsc,
- const struct dsc_config *dsc_cfg,
- const struct dsc_optc_config *dsc_optc_cfg);
+bool hwss_add_dsc_set_config(struct block_sequence_state *seq_state,
+ struct display_stream_compressor *dsc);
+
+/* Composes DSC sub-sequence (prepare, set config, enable with OPP) for a pipe. */
+bool hwss_add_dsc_sequence_for_pipe(struct block_sequence_state *seq_state,
+ struct pipe_ctx *pipe_ctx, int opp_cnt, uint32_t dsc_padding,
+ struct dsc_optc_config *dsc_optc_cfg);
+
+/* Composes full DSC sequence (DCCG DTO clocks, DSC, OPP, TG) for a stream. */
+bool hwss_add_dsc_sequence_for_stream(struct block_sequence_state *seq_state,
+ struct pipe_ctx *pipe_ctx, uint32_t dsc_padding,
+ struct dsc_optc_config *dsc_optc_cfg);
void hwss_add_stream_enc_dp_set_dsc_config(struct block_sequence_state *seq_state,
struct stream_encoder *stream_enc,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index c009d0fb14ca..ec503d3541c9 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -767,14 +767,25 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, dsc->inst, dsc_cfg.dc_dsc_cfg.num_slices_h);
- dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
+ if (!dsc->funcs->dsc_prepare_config(dsc, &dsc_cfg, &dsc_optc_cfg)) {
+ ASSERT(false);
+ return;
+ }
+ dsc->funcs->dsc_set_config(dsc);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
+ ASSERT(odm_dsc);
+ if (!odm_dsc)
+ return;
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst, dsc_cfg.dc_dsc_cfg.num_slices_h);
- odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
+ if (!odm_dsc->funcs->dsc_prepare_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg)) {
+ ASSERT(false);
+ return;
+ }
+ odm_dsc->funcs->dsc_set_config(odm_dsc);
odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
}
dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 10/17] drm/amd/display: Assign alt wa bit in fams2 cmd
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (8 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 09/17] drm/amd/display: Prepare DSC configuration before BLS execution Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 11/17] drm/amd/display: Update link training no timeout behaviour on HDMI Roman.Li
` (7 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Alvin Lee, Dillon Varone
From: Alvin Lee <Alvin.Lee2@amd.com>
[Description]
Assign the workaround bit to ensure it propagates to FW
Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index 37248ecc3c08..0485ff5217f1 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -1949,6 +1949,7 @@ static void dc_dmub_srv_ib_based_fams2_update_config(struct dc *dc,
config->global.features.bits.enable_stall_recovery = dc->debug.fams2_config.bits.enable_stall_recovery;
config->global.features.bits.enable_offload_flip = dc->debug.fams2_config.bits.enable_offload_flip;
config->global.features.bits.enable_debug = dc->debug.fams2_config.bits.enable_debug;
+ config->global.features.bits.alternate_channel_workaround = dc->debug.fams2_config.bits.alternate_channel_workaround;
/* construct per-stream configs */
for (i = 0; i < context->bw_ctx.bw.dcn.fams2_global_config.num_streams; i++) {
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 11/17] drm/amd/display: Update link training no timeout behaviour on HDMI
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (9 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 10/17] drm/amd/display: Assign alt wa bit in fams2 cmd Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 12/17] drm/amd/display: Revert "avoid to write signal specific for tmds" Roman.Li
` (6 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Relja Vojvodic, Chris Park
From: Relja Vojvodic <Relja.Vojvodic@amd.com>
[Why & How]
- HMDI link training compliance testing fails when no timeout bit is
set
- Update condition to skip some link training logic when no timeout
is set
Reviewed-by: Chris Park <chris.park@amd.com>
Signed-off-by: Relja Vojvodic <Relja.Vojvodic@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
.../amd/display/dc/link/protocols/link_hdmi_frl.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
index 2f1b8c0bc8f8..5e0979ac3dcf 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
@@ -561,6 +561,16 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s
prev_flt_update = scdc_update.fields.FLT_UPDATE;
}
+ if (flt_no_timeout) {
+ offset = HDMI_SCDC_SOURCE_TEST_REQ;
+ link_query_ddc_data(ddc_service, slave_address, &offset,
+ sizeof(offset), &test_req.byte, sizeof(test_req.byte));
+ if (test_req.fields.FLT_NO_TIMEOUT == 0) {
+ FRL_INFO("FRL TEST REQ: FLT_no_timeout = %d \n", test_req.fields.FLT_NO_TIMEOUT);
+ return LINK_RESULT_SUCCESS;
+ }
+ }
+
/*Set TxFFE = TxFFE0*/
/*Program FFE_Levels - scdc_config has this field at 0 */
if (override_FFE) {
@@ -583,7 +593,7 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s
FRL_INFO("FRL LINK TRAINING: TxFFE = %d.\n", current_FFE);
override_FFE = false;
}
- if (scdc_update.fields.FLT_UPDATE || flt_no_timeout) {
+ if (scdc_update.fields.FLT_UPDATE) {
offset = HDMI_SCDC_LTP_REQ;
link_query_ddc_data(ddc_service, slave_address,
&offset, sizeof(offset), ltp_req.byte,
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 12/17] drm/amd/display: Revert "avoid to write signal specific for tmds"
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (10 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 11/17] drm/amd/display: Update link training no timeout behaviour on HDMI Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 13/17] drm/amd/display: Handle virtual link encoder Roman.Li
` (5 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Joshua Aberback, Martin Leung
From: Joshua Aberback <joshua.aberback@amd.com>
This reverts commit 8be7aa94fe09165047495120fa4d66a9aa5ca1e4.
The change regressed HDMI output on the TMDS-to-FRL switch.
Reviewed-by: Martin Leung <martin.leung@amd.com>
Signed-off-by: Joshua Aberback <joshua.aberback@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 2 --
drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c | 8 +++-----
drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h | 1 -
3 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index ec503d3541c9..0d3b65d40807 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -1909,7 +1909,6 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
write_scdc_data(
stream->link->ddc,
stream->phy_pix_clk,
- dc_is_hdmi_frl_signal(pipe_ctx->stream->signal),
(stream->timing.flags.LTE_340MCSC_SCRAMBLE != 0));
if (dc->debug.enable_hdmi_idcc) {
@@ -2450,7 +2449,6 @@ enum dc_status link_set_dpms_off(struct pipe_ctx *pipe_ctx)
write_scdc_data(
link->ddc,
165000,//vbios only handles 165Mhz.
- dc_is_hdmi_frl_signal(stream->signal),
false);
if (masked_chip_caps == AMD_EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
/* DP159, Retimer settings */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
index 3fbfc6e2594b..db798656c8a8 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
@@ -570,7 +570,6 @@ struct ddc *get_ddc_pin(struct ddc_service *ddc_service)
void write_scdc_data(struct ddc_service *ddc_service,
uint32_t pix_clk,
- bool is_frl,
bool lte_340_scramble)
{
bool over_340_mhz = pix_clk > 340000 ? 1 : 0;
@@ -587,10 +586,9 @@ void write_scdc_data(struct ddc_service *ddc_service,
(ddc_service->link->local_sink->edid_caps.panel_patch.skip_scdc_overwrite ||
!ddc_service->link->local_sink->edid_caps.scdc_present))
return;
- if (is_frl) {
- hdmi_frl_LTS_clear_Link_Setting(ddc_service);
- hdmi_frl_LTS_clear_Update_flag(ddc_service);
- }
+ hdmi_frl_LTS_clear_Link_Setting(ddc_service);
+ hdmi_frl_LTS_clear_Update_flag(ddc_service);
+
link_query_ddc_data(ddc_service, slave_address, &offset,
sizeof(offset), &sink_version, sizeof(sink_version));
if (sink_version == 1) {
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h
index 200823954fc6..fdd8a3dce97f 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h
@@ -91,7 +91,6 @@ uint32_t link_get_fixed_vs_pe_retimer_write_address(struct dc_link *link);
void write_scdc_data(
struct ddc_service *ddc_service,
uint32_t pix_clk,
- bool is_frl,
bool lte_340_scramble);
void read_scdc_data(
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 13/17] drm/amd/display: Handle virtual link encoder
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (11 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 12/17] drm/amd/display: Revert "avoid to write signal specific for tmds" Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 14/17] drm/amd/display: Add dcn42b project id Roman.Li
` (4 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Sridevi Arvindekar, Ilya Bakoulin,
Sridevi Arvindekar
From: Sridevi Arvindekar <Sridevi.Arvindekar@amd.com>
[Why/How]
Fix check for virtual link encoder
Reviewed-by: Ilya Bakoulin <ilya.bakoulin@amd.com>
Signed-off-by: Sridevi Arvindekar <sridevi.arvindekar@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 7e42790ad575..187486d978da 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -3019,7 +3019,7 @@ static inline int find_fixed_dio_link_enc(const struct dc_link *link)
{
/* virtual links own their link encoder directly and are never
* registered into pool->link_encoders[]. */
- if (link->connector_signal == SIGNAL_TYPE_VIRTUAL)
+ if (link->link_id.id == CONNECTOR_ID_VIRTUAL)
return -1;
/* the 8b10b dp phy can only use fixed link encoder */
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 14/17] drm/amd/display: Add dcn42b project id
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (12 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 13/17] drm/amd/display: Handle virtual link encoder Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 15/17] drm/amd/display: Add debug option to override low power SR latencies Roman.Li
` (3 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Dillon Varone, Austin Zheng
From: Dillon Varone <Dillon.Varone@amd.com>
[WHY&HOW]
Add project ID to distinguish dcn42b from dcn42.
Reviewed-by: Austin Zheng <austin.zheng@amd.com>
Signed-off-by: Dillon Varone <Dillon.Varone@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h | 1 +
.../amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.c | 1 +
.../display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c | 1 +
.../display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c | 1 +
.../amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c | 1 +
.../amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c | 1 +
.../display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c | 1 +
.../dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c | 1 +
8 files changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
index 5a8550f592ca..75a24a85775e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
@@ -20,6 +20,7 @@ enum dml2_project_id {
dml2_project_dcn4x_stage2,
dml2_project_dcn4x_stage2_auto_drr_svp,
dml2_project_dcn42,
+ dml2_project_dcn42b,
dml2_project_dcn4x_utm,
dml2_project_dcn5x,
dml2_project_dcn5x_utm,
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.c
index 92cdc11c1892..ddf4f55cc261 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.c
@@ -16,6 +16,7 @@ bool dml2_cga_create(enum dml2_project_id project_id, struct dml2_clock_granular
switch (project_id) {
case dml2_project_dcn4x_stage1:
case dml2_project_dcn42:
+ case dml2_project_dcn42b:
case dml2_project_dcn4x_stage2:
case dml2_project_dcn4x_stage2_auto_drr_svp:
case dml2_project_dcn4x_utm:
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
index 0800c667f204..320f60cfa165 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
@@ -35,6 +35,7 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance
result = true;
break;
case dml2_project_dcn42:
+ case dml2_project_dcn42b:
out->initialize = &core_dcn42_initialize;
out->mode_support = &core_dcn4_mode_support;
out->mode_programming = &core_dcn4_mode_programming;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
index 528ebadb87e1..ec09c69482ec 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
@@ -45,6 +45,7 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
result = true;
break;
case dml2_project_dcn42:
+ case dml2_project_dcn42b:
out->map_mode_to_soc_dpm = &dpmm_dcn4_map_mode_to_soc_dpm;
out->map_watermarks = &dpmm_dcn42_map_watermarks;
result = true;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
index a1d63148b6e5..0105fb890792 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
@@ -33,6 +33,7 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance *
result = true;
break;
case dml2_project_dcn42:
+ case dml2_project_dcn42b:
out->build_min_clock_table = &mcg_dcn42_build_min_clock_table;
result = true;
break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
index 44438792931c..997a2be30ef9 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
@@ -63,6 +63,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *
result = true;
break;
case dml2_project_dcn42:
+ case dml2_project_dcn42b:
out->initialize = pmo_dcn42_initialize;
out->init_for_vmin = pmo_dcn4_fams2_init_for_vmin;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
index aaca0a450f0e..95558710a834 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
@@ -19,6 +19,7 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out)
case dml2_project_dcn4x_stage2:
case dml2_project_dcn4x_stage2_auto_drr_svp:
case dml2_project_dcn42:
+ case dml2_project_dcn42b:
return dml2_top_soc15_initialize_instance(in_out);
case dml2_project_dcn5x_utm:
case dml2_project_dcn6x_soc_var_a:
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c
index 2faf28f753fe..68a6b1a4f2a7 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c
@@ -20,6 +20,7 @@ bool dml2_utm_soc_bb_create(enum dml2_project_id project_id, struct dml2_utm_soc
case dml2_project_dcn5x:
case dml2_project_dcn4x_stage1:
case dml2_project_dcn42:
+ case dml2_project_dcn42b:
case dml2_project_dcn4x_stage2:
case dml2_project_dcn4x_stage2_auto_drr_svp:
case dml2_project_invalid:
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 15/17] drm/amd/display: Add debug option to override low power SR latencies
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (13 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 14/17] drm/amd/display: Add dcn42b project id Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 16/17] drm/amd/display: Send HDMI VRR metadata in VTEM info packet slot Roman.Li
` (2 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Alvin Lee, Austin Zheng
From: Alvin Lee <Alvin.Lee2@amd.com>
[Description]
- Add debug options to override low power SR latencies
- Match regular SR latency debug override
Reviewed-by: Austin Zheng <austin.zheng@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/dc.h | 2 +
.../dcn60/dcn60_soc_and_ip_translator.c | 39 ++++++++++++++++++-
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 957e15e4a84c..5cd7699e3e84 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1042,6 +1042,8 @@ struct dc_virtual_addr_space_config {
struct dc_bounding_box_overrides {
unsigned int sr_exit_time_ns;
unsigned int sr_enter_plus_exit_time_ns;
+ unsigned int sr_lp_exit_time_ns;
+ unsigned int sr_lp_enter_plus_exit_time_ns;
unsigned int sr_exit_z8_time_ns;
unsigned int sr_enter_plus_exit_z8_time_ns;
unsigned int urgent_latency_ns;
diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.c
index f1ee2225e9b8..aef527c7584b 100644
--- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.c
+++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.c
@@ -79,6 +79,43 @@ static void dcn60_update_soc_bb_with_values_from_dmub(struct dml2_soc_bb *soc_bb
min_alt_ch_carveout_size_mb;
}
+static void dcn60_update_soc_bb_with_values_from_software_policy(struct dml2_soc_bb *soc_bb, const struct dc *dc)
+{
+ /* set if the value is provided */
+ if (dc->bb_overrides.sr_exit_time_ns)
+ soc_bb->power_management_parameters.stutter_exit_latency_us =
+ dc->bb_overrides.sr_exit_time_ns / 1000.0;
+
+ if (dc->bb_overrides.sr_enter_plus_exit_time_ns)
+ soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us =
+ dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
+
+ if (dc->bb_overrides.dram_clock_change_latency_ns)
+ soc_bb->power_management_parameters.dram_clk_change_blackout_us =
+ dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
+
+ if (dc->bb_overrides.fclk_clock_change_latency_ns)
+ soc_bb->power_management_parameters.fclk_change_blackout_us =
+ dc->bb_overrides.fclk_clock_change_latency_ns / 1000.0;
+
+ if (dc->bb_overrides.sr_exit_z8_time_ns)
+ soc_bb->power_management_parameters.z8_stutter_exit_latency_us =
+ dc->bb_overrides.sr_exit_z8_time_ns / 1000.0;
+
+ if (dc->bb_overrides.sr_enter_plus_exit_z8_time_ns)
+ soc_bb->power_management_parameters.z8_stutter_enter_plus_exit_latency_us =
+ dc->bb_overrides.sr_enter_plus_exit_z8_time_ns / 1000.0;
+
+ /* low power stutter latencies exist only on DCN6 and above */
+ if (dc->bb_overrides.sr_lp_exit_time_ns)
+ soc_bb->power_management_parameters.low_power_stutter_exit_latency_us =
+ dc->bb_overrides.sr_lp_exit_time_ns / 1000.0;
+
+ if (dc->bb_overrides.sr_lp_enter_plus_exit_time_ns)
+ soc_bb->power_management_parameters.low_power_stutter_enter_plus_exit_latency_us =
+ dc->bb_overrides.sr_lp_enter_plus_exit_time_ns / 1000.0;
+}
+
static void apply_soc_bb_updates(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config)
{
/* Individual modification can be overwritten even if it was obtained by a previous function.
@@ -89,7 +126,7 @@ static void apply_soc_bb_updates(struct dml2_soc_bb *soc_bb, const struct dc *dc
dcn60_update_soc_bb_with_values_from_dmub(soc_bb, config);
dcn401_update_soc_bb_with_values_from_clk_mgr(soc_bb, dc, config);
dcn401_update_soc_bb_with_values_from_vbios(soc_bb, dc);
- dcn401_update_soc_bb_with_values_from_software_policy(soc_bb, dc);
+ dcn60_update_soc_bb_with_values_from_software_policy(soc_bb, dc);
}
static void dcn60_get_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config)
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 16/17] drm/amd/display: Send HDMI VRR metadata in VTEM info packet slot
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (14 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 15/17] drm/amd/display: Add debug option to override low power SR latencies Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-02 19:32 ` [PATCH 17/17] drm/amd/display: Promote DC to 3.2.401 Roman.Li
2026-10-05 13:30 ` [PATCH 00/17] DC Patches October 2, 2026 Wheeler, Daniel
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen
From: Ivan Lipski <ivan.lipski@amd.com>
[Why]
Brief blank on HDMI each time VRR engaged and disengaged, with no modeset
at either transition.
amdgpu_dm_update_freesync_state_on_stream() built the VTEM on top of the
buffer holding the AMD FreeSync SPD payload, which becomes
stream->vrr_infopacket. DC routes that to HDMI generic slot 3 (SPD) and
vtem_infopacket to slot 6 (VTEM), and vtem_infopacket was never populated.
So slot 3 carried a VTEM payload the sink parsed as an SPD
InfoFrame, no VTEM was sent, and v_total varied with no valid metadata
describing it. DP uses the VSC/AS-SDP path and is unaffected.
[How]
Build the VTEM into a separate vtem_infopacket, gated on the sink not
advertising AMD FreeSync. Track it in dm_crtc_state, include it in the
freesync_vrr_info_changed comparison and the reset path, and pass it
through bundle->stream_update.vtem_infopacket.
Reviewed-by: Jerry Zuo <jerry.zuo@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 +
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 26 +++++++++++++++----
3 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 6e5dbe0bd82e..f3ed3fef59f9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4141,6 +4141,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
if (acrtc_state->freesync_vrr_info_changed) {
bundle->stream_update.vrr_infopacket =
&acrtc_state->stream->vrr_infopacket;
+ bundle->stream_update.vtem_infopacket =
+ &acrtc_state->stream->vtem_infopacket;
bundle->stream_update.vsp_infopacket =
&acrtc_state->stream->vsp_infopacket;
stream_update_needed = true;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 2ead9bc8e439..594d275918d5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1076,6 +1076,7 @@ struct dm_crtc_state {
bool vrr_supported;
struct mod_freesync_config freesync_config;
struct dc_info_packet vrr_infopacket;
+ struct dc_info_packet vtem_infopacket;
int abm_level;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
index 1d9148ccfd4f..f4ce389fd0aa 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
@@ -107,6 +107,8 @@ void amdgpu_dm_reset_freesync_config_for_crtc(
memset(&new_crtc_state->vrr_infopacket, 0,
sizeof(new_crtc_state->vrr_infopacket));
+ memset(&new_crtc_state->vtem_infopacket, 0,
+ sizeof(new_crtc_state->vtem_infopacket));
}
EXPORT_SYMBOL_IF_KUNIT(amdgpu_dm_reset_freesync_config_for_crtc);
@@ -172,6 +174,7 @@ void amdgpu_dm_update_freesync_state_on_stream(
{
struct mod_vrr_params vrr_params;
struct dc_info_packet vrr_infopacket = {0};
+ struct dc_info_packet vtem_infopacket = {0};
struct amdgpu_device *adev = dm->adev;
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
unsigned long flags;
@@ -238,21 +241,34 @@ void amdgpu_dm_update_freesync_state_on_stream(
&vrr_infopacket,
pack_sdp_v1_3);
- /* Per HDMI 2.1, VTEM is valid on TMDS as well as FRL */
- if (new_stream->signal == SIGNAL_TYPE_HDMI_FRL ||
- (new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A &&
- aconn && aconn->base.display_info.hdmi.vrr_cap.supported))
- mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
+ /*
+ * If the sink does not support FreeSync, but it does support VRR,
+ * we need to build a VTEM packet to enable VRR.
+ */
+ if (aconn && !aconn->vsdb_info.freesync_supported &&
+ aconn->base.display_info.hdmi.vrr_cap.supported &&
+ (new_stream->signal == SIGNAL_TYPE_HDMI_FRL ||
+ new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)) {
+ mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vtem_infopacket);
+ memset(&vrr_infopacket, 0, sizeof(vrr_infopacket));
+ }
new_crtc_state->freesync_vrr_info_changed |=
(memcmp(&new_crtc_state->vrr_infopacket,
&vrr_infopacket,
sizeof(vrr_infopacket)) != 0);
+ new_crtc_state->freesync_vrr_info_changed |=
+ (memcmp(&new_crtc_state->vtem_infopacket,
+ &vtem_infopacket,
+ sizeof(vtem_infopacket)) != 0);
+
acrtc->dm_irq_params.vrr_params = vrr_params;
new_crtc_state->vrr_infopacket = vrr_infopacket;
+ new_crtc_state->vtem_infopacket = vtem_infopacket;
new_stream->vrr_infopacket = vrr_infopacket;
+ new_stream->vtem_infopacket = vtem_infopacket;
new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 17/17] drm/amd/display: Promote DC to 3.2.401
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (15 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 16/17] drm/amd/display: Send HDMI VRR metadata in VTEM info packet slot Roman.Li
@ 2026-10-02 19:32 ` Roman.Li
2026-10-05 13:30 ` [PATCH 00/17] DC Patches October 2, 2026 Wheeler, Daniel
17 siblings, 0 replies; 19+ messages in thread
From: Roman.Li @ 2026-10-02 19:32 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, Alex Hung,
James Lin, Chenyu Chen, Ashwin Santhosh
From: Ashwin Santhosh <Ashwin.Santhosh@amd.com>
This version brings along the following updates:
- Add HDMI RR and SCDC skips.
- Add debug option to override low power SR latencies.
- Allow skipping link bandwidth clear.
- Handle virtual link encoder.
- Improve MCM shaper/3DLUT programming and DTN logging.
- Only reprogram DRR when v_total values change.
- Refactor DMUB fast lock sequencing.
- Send HDMI VRR metadata in VTEM info packet slot.
- Set cursor_offload for all pipes for a given stream.
- Skip link off frame count for general UI.
- Update link training no timeout behaviour on HDMI.
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Ashwin Santhosh <Ashwin.Santhosh@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
drivers/gpu/drm/amd/display/dc/dc.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 5cd7699e3e84..d3c484f45333 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -68,7 +68,7 @@ struct dcn_dsc_reg_state;
struct dcn_optc_reg_state;
struct dcn_dccg_reg_state;
-#define DC_VER "3.2.400"
+#define DC_VER "3.2.401"
/**
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* RE: [PATCH 00/17] DC Patches October 2, 2026
2026-10-02 19:32 [PATCH 00/17] DC Patches October 2, 2026 Roman.Li
` (16 preceding siblings ...)
2026-10-02 19:32 ` [PATCH 17/17] drm/amd/display: Promote DC to 3.2.401 Roman.Li
@ 2026-10-05 13:30 ` Wheeler, Daniel
17 siblings, 0 replies; 19+ messages in thread
From: Wheeler, Daniel @ 2026-10-05 13:30 UTC (permalink / raw)
To: Li, Roman, amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry, Li, Sun peng (Leo), Li, Roman, Lin, Wayne,
Chung, ChiaHsuan (Tom), Zuo, Jerry, Wu, Ray, LIPSKI, IVAN,
Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu, Li, Roman
Public
Hi all,
This week this patchset was tested on 4 systems, two dGPU and two APU based, and tested across multiple display and connection types.
APU
* Single Display eDP -> 1080p 60hz, 1920x1200 165hz, 3840x2400 60hz
* Single Display DP (SST DSC) -> 4k144hz, 4k240hz
* Multi display -> eDP + DP/HDMI/USB-C -> 1080p 60hz eDP + 4k 144hz, 4k 240hz (Includes USB-C to DP/HDMI adapters)
* Thunderbolt -> LG Ultrafine 5k
* MST DSC -> Cable Matters 101075 (DP to 3x DP) with 3x 4k60hz displays, HP Hook G2 with 2x 4k60hz displays
* USB 4 -> HP Hook G4, Lenovo Thunderbolt Dock, both with 2x 4k60hz DP and 1x 4k60hz HDMI displays
* SST PCON -> Club3D CAC-1085 + 1x 4k 144hz, FRL3, at a max resolution supported by the dongle of 4k 120hz YUV420 12bpc.
* MST PCON -> 1x 4k 144hz, FRL3, at a max resolution supported by the adapter of 4k 120hz RGB 8bpc.
DGPU
* Single Display DP (SST DSC) -> 4k144hz, 4k240hz
* Multiple Display DP -> 4k240hz + 4k144hz
* MST (Startech MST14DP123DP [DP to 3x DP] and 2x 4k 60hz displays)
* MST DSC (with Cable Matters 101075 [DP to 3x DP] with 3x 4k60hz displays)
The testing is a mix of automated and manual tests. Manual testing includes (but is not limited to)
* Changing display configurations and settings
* Video/Audio playback
* Benchmark testing
* Suspend/Resume testing
* Feature testing (Freesync, HDCP, etc.)
Automated testing includes (but is not limited to)
* Script testing (scripts to automate some of the manual checks)
* IGT testing
The testing is mainly tested on the following displays, but occasionally there are tests with other displays
* Samsung G8 Neo 4k240hz
* Samsung QN55QN95B 4k 120hz
* Acer XV322QKKV 4k144hz
* HP U27 4k Wireless 4k60hz
* LG 27UD58B 4k60hz
* LG 32UN650WA 4k60hz
* LG Ultrafine 5k 5k60hz
* AU Optronics B140HAN01.1 1080p 60hz eDP
* AU Optronics B160UAN01.J 1920x1200 165hz eDP
* Samsung ATNA60YV02-0 3840x2400 60Hz OLED eDP
The patchset consists of the amd-staging-drm-next branch (Head commit -> 0fe07578aeb611d89ceacacfa77345dbeba45bc4 -> drm/amdgpu: Fix race on ualink_handle_lo in UALink handle export) with new patches added on top of it.
Tested on Ubuntu 26.04, on Gnome Wayland.
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Thank you,
Dan Wheeler
Sr. Technologist | AMD
SW Display
------------------------------------------------------------------------------------------------------------------
1 Commerce Valley Dr E, Thornhill, ON L3T 7X6
amd.com
-----Original Message-----
From: Roman.Li@amd.com <Roman.Li@amd.com>
Sent: Friday, October 2, 2026 3:32 PM
To: amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Li, Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung, ChiaHsuan (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry <Jerry.Zuo@amd.com>; Wheeler, Daniel <Daniel.Wheeler@amd.com>; Wu, Ray <Ray.Wu@amd.com>; LIPSKI, IVAN <IVAN.LIPSKI@amd.com>; Hung, Alex <Alex.Hung@amd.com>; Lin, Ping Lei <PingLei.Lin@amd.com>; Chen, Chen-Yu <Chen-Yu.Chen@amd.com>; Li, Roman <Roman.Li@amd.com>
Subject: [PATCH 00/17] DC Patches October 2, 2026
From: Roman Li <Roman.Li@amd.com>
This DC 3.2.401 patchset brings improvements in multiple areas. In summary, we have:
* HDMI: RR and SCDC skips, link-training timeout behaviour, VRR metadata in the
VTEM info packet, and a TMDS output regression revert;
* MCM shaper/3DLUT programming and DTN logging improvements;
* DMUB: fast-lock sequencing refactor and FAMS2 command update;
* DSC configuration preparation and DRR reprogramming optimizations;
* Replay/low-power, eDP link-bandwidth, cursor offload, and virtual link
encoder handling;
* New DCN42b project ID.
Cc: Dan Wheeler <daniel.wheeler@amd.com>
Allen Li (1):
drm/amd/display: Skip link off frame count for general UI
Alvin Lee (3):
drm/amd/display: Set cursor_offload for all pipes for a given stream
drm/amd/display: Assign alt wa bit in fams2 cmd
drm/amd/display: Add debug option to override low power SR latencies
Aric Cyr (1):
drm/amd/display: only reprogram DRR when v_total values change
Ashwin Santhosh (1):
drm/amd/display: Promote DC to 3.2.401
Dillon Varone (1):
drm/amd/display: Add dcn42b project id
Harry Wentland (2):
drm/amd/display: enable shaper when programming 3DLUT
drm/amd/display: log MCM shaper and 3D LUT mode in the DTN log
Ilya Bakoulin (1):
drm/amd/display: Add HDMI RR and SCDC skips
Ivan Lipski (1):
drm/amd/display: Send HDMI VRR metadata in VTEM info packet slot
Joshua Aberback (1):
drm/amd/display: Revert "avoid to write signal specific for tmds"
Martin Tsai (1):
drm/amd/display: allow skipping link bandwidth clear
Rafal Ostrowski (2):
drm/amd/display: Refactor DMUB fast lock sequencing
drm/amd/display: Prepare DSC configuration before BLS execution
Relja Vojvodic (1):
drm/amd/display: Update link training no timeout behaviour on HDMI
Sridevi Arvindekar (1):
drm/amd/display: Handle virtual link encoder
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 +
.../amd/display/amdgpu_dm/amdgpu_dm_color.c | 1 +
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 26 +-
drivers/gpu/drm/amd/display/dc/core/dc.c | 101 +---
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 522 ++++++++++++------
.../drm/amd/display/dc/core/dc_link_exports.c | 5 +
.../gpu/drm/amd/display/dc/core/dc_resource.c | 2 +-
.../gpu/drm/amd/display/dc/core/dc_stream.c | 36 +-
drivers/gpu/drm/amd/display/dc/dc.h | 8 +-
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 1 +
drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 1 +
drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +
.../drm/amd/display/dc/dce/dmub_hw_lock_mgr.c | 12 +-
.../dc/dml2_0/dml21/inc/dml_top_types.h | 1 +
.../dml21/src/dml2_cga/dml2_cga_factory.c | 1 +
.../dml21/src/dml2_core/dml2_core_factory.c | 1 +
.../dml21/src/dml2_dpmm/dml2_dpmm_factory.c | 1 +
.../dml21/src/dml2_mcg/dml2_mcg_factory.c | 1 +
.../dml21/src/dml2_pmo/dml2_pmo_factory.c | 1 +
.../dml21/src/dml2_top/dml2_top_interfaces.c | 1 +
.../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c | 1 +
.../drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c | 48 +- .../drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h | 13 +-
.../drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c | 1 +
.../amd/display/dc/dsc/dcn401/dcn401_dsc.c | 34 +-
.../amd/display/dc/dsc/dcn401/dcn401_dsc.h | 5 +-
.../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c | 41 +-
.../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h | 3 +-
drivers/gpu/drm/amd/display/dc/dsc/dsc.h | 3 +-
.../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 17 +-
.../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 11 +-
.../amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 14 +-
.../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 32 +-
.../amd/display/dc/hwss/dcn32/dcn32_hwseq.h | 2 +-
.../amd/display/dc/hwss/dcn32/dcn32_init.c | 2 +-
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 99 ++--
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 12 +-
.../amd/display/dc/hwss/dcn35/dcn35_init.c | 2 +
.../amd/display/dc/hwss/dcn351/dcn351_init.c | 2 +
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 67 +--
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 2 +-
.../amd/display/dc/hwss/dcn401/dcn401_init.c | 2 +-
.../amd/display/dc/hwss/dcn42/dcn42_hwseq.c | 16 +-
.../amd/display/dc/hwss/dcn42/dcn42_hwseq.h | 2 +-
.../amd/display/dc/hwss/dcn42/dcn42_init.c | 2 +-
.../amd/display/dc/hwss/dcn50/dcn50_hwseq.c | 11 +-
.../amd/display/dc/hwss/dcn60/dcn60_init.c | 2 +-
.../drm/amd/display/dc/hwss/hw_sequencer.h | 108 ++--
.../drm/amd/display/dc/link/link_detection.c | 4 +-
.../gpu/drm/amd/display/dc/link/link_dpms.c | 17 +-
.../amd/display/dc/link/protocols/link_ddc.c | 17 +-
.../amd/display/dc/link/protocols/link_ddc.h | 1 -
.../dc/link/protocols/link_dp_training.c | 20 +-
.../display/dc/link/protocols/link_hdmi_frl.c | 12 +-
.../amd/display/dc/mpc/dcn401/dcn401_mpc.c | 18 +-
.../dcn60/dcn60_soc_and_ip_translator.c | 39 +-
.../amd/display/include/link_service_types.h | 1 +
.../amd/display/modules/power/power_replay.c | 6 +-
59 files changed, 853 insertions(+), 563 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 19+ messages in thread