* [PATCH 00/28] DC Patches Oct 27, 2026
@ 2026-10-27 23:16 Alex Hung
2026-10-27 23:16 ` [PATCH 01/28] drm/amd/display: Use DCN6 driver_if for PPCLK_e enum Alex Hung
` (28 more replies)
0 siblings, 29 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:16 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen
This DC patchset brings improvements in multiple areas. In summary, we have:
* Fixes on mode detection, DSC with DPMS off and HUBP DET reset
* Fixes on DDC pins and missing OTG_CRC1 regs for DCN3.1.x
* Improvements on DCN6 FAMS immediate restore and PPCLK_e enum
* Improvements on DSCCLK check and DSC slice calc policy
* Improvements on Replay frame update interval and debug mode
* Improvements on DML VM rounding and P-State optimizer
* Removal of DCN401 RDPCS PHY state reads
* New debug options for HDMI VRR and visual confirm
* More KUnit tests for connector, CRC, color and backlight
Cc: Dan Wheeler <daniel.wheeler@amd.com>
Alex Hung (5):
drm/amd/display: Avoid closing unowned DDC pins
drm/amd/display: Add more backlight Kunit tests
drm/amd/display: Add more color KUnit tests
drm/amd/display: Add more CRC KUnit tests
drm/amd/display: Add more connector KUnit tests
Allen Li (1):
drm/amd/display: Allow bypassing link_off_frame_count check for replay
debug mode
Alvin Lee (4):
drm/amd/display: Add visual confirm full viewport debug option
drm/amd/display: Indicate wait_resp based on FAMS even in disable path
drm/amd/display: Enable immediate restore for FAMS on DCN6
drm/amd/display: Update alt shared lib to use dynamic state
Austin Zheng (2):
drm/amd/display: Update Rounding For VM stage groups
drm/amd/display: Parameterize FCLK/PPT/Temp Read P-State Optimizer
Dmitry Artemenko (2):
drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.4
drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.2
Dominik Kaszewski (1):
drm/amd/display: Clarify endianness error
Fangzhi Zuo (2):
drm/amd/display: Fix unadvertised mode detection
drm/amd/display: Add debugfs override for HDMI VRR
George Shen (1):
drm/amd/display: Skip dsc sequence for stream if dpms off
Ilya Bakoulin (2):
drm/amd/display: Adjust DSC slice calc. policy
drm/amd/display: Expand DSCCLK support check
Ivan Lipski (2):
drm/amd/display: Use DCN6 driver_if for PPCLK_e enum
drm/amd/display: Configure alternate-channel apertures
Meenakshikumar Somasundaram (1):
drm/amd/display: Support replay frame update interval
Rafal Ostrowski (1):
drm/amd/display: Decouple FAMS2 config update from dc/dc_state and add
BLS opcode
Roman Li (1):
drm/amd/display: Reset DET of HUBPs without a plane before outstanding
updates
Taimur Hassan (2):
drm/amd/display: [FW Promotion] Release 0.1.82.0
drm/amd/display: Promote DC to 3.2.405
Tony Cheng (1):
drm/amd/display: Remove DCN401 RDPCS PHY state reads
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 +
.../display/amdgpu_dm/amdgpu_dm_connector.c | 110 +++++++++++++---
.../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 30 +++++
.../amd/display/amdgpu_dm/amdgpu_dm_dmub.c | 63 +++++++++
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 2 +-
.../tests/amdgpu_dm_backlight_test.c | 79 ++++++++++-
.../amdgpu_dm/tests/amdgpu_dm_color_test.c | 18 +++
.../tests/amdgpu_dm_connector_test.c | 118 +++++++++++++++--
.../amdgpu_dm/tests/amdgpu_dm_crc_test.c | 124 ++++++++++++++++++
.../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c | 37 +++++-
drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +-
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 69 ++++++++++
.../gpu/drm/amd/display/dc/core/dc_resource.c | 47 ++++++-
drivers/gpu/drm/amd/display/dc/dc.h | 4 +-
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 113 ++++++++--------
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 27 +++-
drivers/gpu/drm/amd/display/dc/dc_types.h | 3 +
.../gpu/drm/amd/display/dc/dce/dmub_replay.c | 1 +
.../gpu/drm/amd/display/dc/dce/dmub_replay.h | 1 -
.../dc/dcn10/dcn10_hw_sequencer_debug.c | 16 +--
.../dc/dio/dcn401/dcn401_dio_link_encoder.c | 22 +---
.../dc/dio/dcn401/dcn401_dio_link_encoder.h | 8 --
.../dml2_core/dml2_core_dcn5_calcs_dchub.c | 2 +-
.../dml2_core_dcn5_funcs_mode_support.c | 24 +++-
.../dml2_core_dcn6_funcs_mode_programming.c | 1 +
.../dml2_core_dcn6_funcs_mode_support.c | 19 ++-
.../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c | 25 ++--
.../alternate_pstate_shared_lib.c | 2 +-
.../alternate_pstate_shared_lib.h | 1 +
.../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c | 1 +
.../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c | 1 +
.../src/inc/dml2_internal_shared_types.h | 4 +
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 24 +++-
.../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c | 1 +
drivers/gpu/drm/amd/display/dc/dsc/dsc.h | 1 +
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 64 ++++++---
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 4 +-
.../amd/display/dc/hwss/dcn401/dcn401_init.c | 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 | 20 ++-
.../drm/amd/display/dc/inc/hw/link_encoder.h | 2 -
.../dc/link/protocols/link_dp_capability.c | 6 +-
.../amd/display/dc/optc/dcn31/dcn31_optc.h | 18 +++
.../amd/display/dc/optc/dcn314/dcn314_optc.h | 18 +++
.../dc/resource/dcn401/dcn401_resource.c | 10 +-
.../dc/resource/dcn60/dcn60_resource.c | 1 +
.../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 31 ++++-
.../amd/display/include/link_service_types.h | 2 +-
49 files changed, 987 insertions(+), 206 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 01/28] drm/amd/display: Use DCN6 driver_if for PPCLK_e enum
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
@ 2026-10-27 23:16 ` Alex Hung
2026-10-27 23:16 ` [PATCH 02/28] drm/amd/display: Allow bypassing link_off_frame_count check for replay debug mode Alex Hung
` (27 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:16 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Alvin Lee
From: Ivan Lipski <ivan.lipski@amd.com>
[WHY & HOW]
dcn60_clk_mgr.c pulled PPCLK_e from dcn401_smu14_driver_if.h which is
incorrect and broke in different use cases.
Use dcn60_smu_driver_if.h instead.
Cc: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
index 9ce378b821dc..29082b186134 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
@@ -21,7 +21,7 @@
#include "dc_state_priv.h"
#include "atomfirmware.h"
-#include "dcn401/dcn401_smu14_driver_if.h"
+#include "dcn60/dcn60_smu_driver_if.h"
#include "dcn/dcn_6_0_0_offset.h"
#include "dcn/dcn_6_0_0_sh_mask.h"
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 02/28] drm/amd/display: Allow bypassing link_off_frame_count check for replay debug mode
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
2026-10-27 23:16 ` [PATCH 01/28] drm/amd/display: Use DCN6 driver_if for PPCLK_e enum Alex Hung
@ 2026-10-27 23:16 ` Alex Hung
2026-10-27 23:16 ` [PATCH 03/28] drm/amd/display: Clarify endianness error Alex Hung
` (26 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:16 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Allen Li, Robin Chen
From: Allen Li <Allen.Li@amd.com>
[WHY & HOW]
Provide a replay debug mode override to bypass the
link_off_frame_count check, enabling Replay when
link_off_frame_count is 0 on high refresh rate/high resolution panels.
Cc: Robin Chen <robin.chen@amd.com>
Signed-off-by: Allen Li <Allen.Li@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/dc/dc_types.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index af241b2bd29a..45fa52011a7f 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -1271,6 +1271,8 @@ struct replay_config {
bool received_frame_skipping_error_hpd;
/* Live capture with CVT is activated */
bool live_capture_with_cvt_activated;
+ /* Bypass link_off_frame_count == 0 check to allow Replay in general_ui scenario */
+ bool bypass_link_off_frame_cnt_check;
};
/* Replay feature flags*/
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 03/28] drm/amd/display: Clarify endianness error
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
2026-10-27 23:16 ` [PATCH 01/28] drm/amd/display: Use DCN6 driver_if for PPCLK_e enum Alex Hung
2026-10-27 23:16 ` [PATCH 02/28] drm/amd/display: Allow bypassing link_off_frame_count check for replay debug mode Alex Hung
@ 2026-10-27 23:16 ` Alex Hung
2026-10-27 23:17 ` [PATCH 04/28] drm/amd/display: Add visual confirm full viewport debug option Alex Hung
` (25 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:16 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Dominik Kaszewski, Wenjing Liu
From: Dominik Kaszewski <dominik.kaszewski@amd.com>
[WHY & HOW]
link_service_types.h requires specifying endianness. The existing
compilation error was too generic and did not immediately point
to the cause of the issue and how to fix it.
Cc: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Dominik Kaszewski <dominik.kaszewski@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/include/link_service_types.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 798d83238828..9026cfddeeea 100644
--- a/drivers/gpu/drm/amd/display/include/link_service_types.h
+++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
@@ -229,7 +229,7 @@ union dpcd_training_lane_set {
uint8_t MAX_SWING_REACHED:1;
uint8_t VOLTAGE_SWING_SET:2;
#else
- #error ARCH not defined!
+ #error "Endianness not defined! Missing LITTLEENDIAN_CPU or BIGENDIAN_CPU"
#endif
} bits;
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 04/28] drm/amd/display: Add visual confirm full viewport debug option
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (2 preceding siblings ...)
2026-10-27 23:16 ` [PATCH 03/28] drm/amd/display: Clarify endianness error Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 05/28] drm/amd/display: Remove DCN401 RDPCS PHY state reads Alex Hung
` (24 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Alvin Lee, Samson Tam
From: Alvin Lee <Alvin.Lee2@amd.com>
[WHAT]
The visual confirm overlay shrinks the recout before the viewport is
derived from it, so the viewport shrinks too. The viewport then
programmed into hardware no longer matches the one DML calculated, since
DML sized the pipe for the full viewport. Keep the viewport full and
shrink only the recout used by the overlay. This is to avoid discrepency
between HW programming and DML calculations.
- Add visual_confirm_full_viewport to struct dc_debug_options.
- Derive the viewport from the full recout on the legacy and SPL paths.
- Shrink the recout for HW only after viewport derivation, including the
dscl_prog_data recout the SPL path programs.
Cc: Samson Tam <samson.tam@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../gpu/drm/amd/display/dc/core/dc_resource.c | 47 ++++++++++++++++---
drivers/gpu/drm/amd/display/dc/dc.h | 2 +
.../dc/resource/dcn60/dcn60_resource.c | 1 +
3 files changed, 43 insertions(+), 7 deletions(-)
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 fa44c68b3340..832286f0c0b1 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1241,9 +1241,15 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx)
pipe_ctx->plane_res.scl_data.recout = shift_rec(
&overlapping_area,
-odm_slice_src.x, -odm_slice_src.y);
- adjust_recout_for_visual_confirm(
- &pipe_ctx->plane_res.scl_data.recout,
- pipe_ctx);
+ /* Non-SPL path: shrinking the recout here, before the viewport is
+ * derived from it, shrinks the viewport too (legacy behavior). To keep
+ * the HW viewport full, skip this and shrink the recout for HW only at
+ * the tail of resource_build_scaling_params.
+ */
+ if (!pipe_ctx->stream->ctx->dc->debug.visual_confirm_full_viewport)
+ adjust_recout_for_visual_confirm(
+ &pipe_ctx->plane_res.scl_data.recout,
+ pipe_ctx);
} else {
/* if there is no overlap, zero recout */
memset(&pipe_ctx->plane_res.scl_data.recout, 0,
@@ -1606,10 +1612,22 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
// Convert pipe_ctx to respective input params for SPL
translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in);
- /* Pass visual confirm debug information */
- calculate_adjust_recout_for_visual_confirm(pipe_ctx,
- &spl_in->debug.visual_confirm_base_offset,
- &spl_in->debug.visual_confirm_dpp_offset);
+ /* Pass visual confirm debug information. These offsets are SPL inputs:
+ * SPL subtracts them from the recout and then derives the viewport from
+ * that shrunk recout, so the viewport shrinks together with the recout.
+ */
+ if (pipe_ctx->stream->ctx->dc->debug.visual_confirm_full_viewport) {
+ /* pass 0 so SPL keeps both recout and viewport full; the recout is
+ * shrunk for HW only at the tail of this function
+ */
+ spl_in->debug.visual_confirm_base_offset = 0;
+ spl_in->debug.visual_confirm_dpp_offset = 0;
+ } else {
+ /* legacy: let SPL shrink both the recout and the viewport */
+ calculate_adjust_recout_for_visual_confirm(pipe_ctx,
+ &spl_in->debug.visual_confirm_base_offset,
+ &spl_in->debug.visual_confirm_dpp_offset);
+ }
// Set SPL output parameters to dscl_prog_data to be used for hw registers
spl_out->dscl_prog_data = resource_get_dscl_prog_data(pipe_ctx);
// Calculate scaler parameters from SPL
@@ -1723,6 +1741,21 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
#ifdef CONFIG_DRM_AMD_DC_FP
}
#endif
+ /* Common tail for both paths (legacy and SPL): the viewport has now been derived from the
+ * full recout, so shrink the recout for HW only. This runs only when
+ * keeping the viewport full; the legacy paths above already shrank the
+ * recout before the viewport was computed.
+ */
+ if (pipe_ctx->stream->ctx->dc->debug.visual_confirm_full_viewport) {
+ adjust_recout_for_visual_confirm(
+ &pipe_ctx->plane_res.scl_data.recout, pipe_ctx);
+ /* SPL programs the HW recout from dscl_prog_data, not scl_data.recout */
+ if (pipe_ctx->stream->ctx->dc->config.use_spl &&
+ !pipe_ctx->stream->ctx->dc->debug.disable_spl)
+ adjust_recout_for_visual_confirm((struct rect *)
+ &pipe_ctx->plane_res.scl_data.dscl_prog_data.recout,
+ pipe_ctx);
+ }
DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n"
"src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n",
__func__,
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index d983bab7eea3..fa4c142ac271 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1350,6 +1350,8 @@ struct dc_debug_options {
uint32_t dml21_custom_derate_at_dpm[DML2_MAX_NUM_DPM_LVL];
bool override_utm_client_qc_profile;
uint8_t utm_client_qc_profiles[4];
+ /* keep HW viewport unchanged by shrinking only recout for visual confirm */
+ bool visual_confirm_full_viewport;
};
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
index 3b70e97c0a6a..f192c95952ab 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
@@ -675,6 +675,7 @@ static const struct dc_debug_options debug_defaults_drv = {
}
},
.force_cositing = CHROMA_COSITING_NONE + 1,
+ .visual_confirm_full_viewport = true,
};
static const struct dc_check_config config_defaults = {
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 05/28] drm/amd/display: Remove DCN401 RDPCS PHY state reads
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (3 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 04/28] drm/amd/display: Add visual confirm full viewport debug option Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 06/28] drm/amd/display: Adjust DSC slice calc. policy Alex Hung
` (23 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Tony Cheng,
Nicholas Kazlauskas
From: Tony Cheng <toncheng@amd.com>
[WHAT]
DMCUB owns the PHY on DCN31+ and can gate its REFCLK. Reading RDPCS
while REFCLK is off can hang the register interface, and only firmware
knows the REFCLK state.
Revert the RDPCS reads added by commit 4b21ed5d08af ("drm/amd/display:
Read DCN401 PHY reset and lane enable state"): the RDPCSTX_PHY_CNTL0/3
register entries, the shift/mask list, dcn401_link_encoder_read_state()
and the link_enc_state fields. Drop the phy_on and phy_active columns
from the get_hw_state LINK section, which read them.
Cc: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Tony Cheng <toncheng@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../dc/dcn10/dcn10_hw_sequencer_debug.c | 16 +++-----------
.../dc/dio/dcn401/dcn401_dio_link_encoder.c | 22 +------------------
.../dc/dio/dcn401/dcn401_dio_link_encoder.h | 8 -------
.../drm/amd/display/dc/inc/hw/link_encoder.h | 2 --
.../dc/resource/dcn401/dcn401_resource.c | 10 +++------
5 files changed, 7 insertions(+), 51 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
index 37a010e0bd6e..395bccdd0f1d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
@@ -524,7 +524,7 @@ static unsigned int dcn10_get_link_states(struct dc *dc, char *pBuf, unsigned in
unsigned int i;
chars_printed = snprintf_count(pBuf, remaining_buffer,
- "link,enc,hpd,dig_en,dig_mode,dig_fe,src_otg,preferred_otg,phy_on,phy_active\n");
+ "link,enc,hpd,dig_en,dig_mode,dig_fe,src_otg,preferred_otg\n");
remaining_buffer -= chars_printed;
pBuf += chars_printed;
@@ -532,8 +532,6 @@ static unsigned int dcn10_get_link_states(struct dc *dc, char *pBuf, unsigned in
struct dc_link *link = dc->links[i];
struct link_encoder *enc = link ? link->link_enc : NULL;
int hpd = -1, dig_en = -1, dig_mode = -1, dig_fe = -1, src_otg = -1;
- int phy_on = -1, phy_active = -1;
- struct link_enc_state s = {0};
if (!enc || link->connector_signal == SIGNAL_TYPE_VIRTUAL)
continue;
@@ -548,19 +546,11 @@ static unsigned int dcn10_get_link_states(struct dc *dc, char *pBuf, unsigned in
dig_fe = enc->funcs->get_dig_frontend(enc);
src_otg = dcn10_dig_source_otg(dc, dig_fe);
}
- s.rdpcs_phy_reset = HW_STATE_NOT_READ;
- s.rdpcs_tx_data_en = HW_STATE_NOT_READ;
- if (enc->funcs->read_state)
- enc->funcs->read_state(enc, &s);
- if (s.rdpcs_phy_reset != HW_STATE_NOT_READ)
- phy_on = s.rdpcs_phy_reset == 0;
- if (s.rdpcs_tx_data_en != HW_STATE_NOT_READ)
- phy_active = s.rdpcs_tx_data_en != 0;
chars_printed = snprintf_count(pBuf, remaining_buffer,
- "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
+ "%d,%d,%d,%d,%d,%d,%d,%d\n",
i, enc->transmitter, hpd, dig_en, dig_mode, dig_fe,
- src_otg, enc->preferred_engine, phy_on, phy_active);
+ src_otg, enc->preferred_engine);
remaining_buffer -= chars_printed;
pBuf += chars_printed;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
index 4d62a5982632..6594fbb3fa43 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
@@ -364,26 +364,6 @@ bool dcn401_is_dig_enabled(struct link_encoder *enc)
return (clk_enabled == 1 && dig_enabled == 1);
}
-void dcn401_link_encoder_read_state(struct link_encoder *enc, struct link_enc_state *s)
-{
- struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
- uint32_t tx0 = 0, tx1 = 0, tx2 = 0, tx3 = 0;
-
- link_enc2_read_state(enc, s);
-
- if (enc10->link_regs->RDPCSTX_PHY_CNTL0)
- REG_GET(RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, &s->rdpcs_phy_reset);
-
- if (enc10->link_regs->RDPCSTX_PHY_CNTL3) {
- REG_GET_4(RDPCSTX_PHY_CNTL3,
- RDPCS_PHY_DP_TX0_DATA_EN, &tx0,
- RDPCS_PHY_DP_TX1_DATA_EN, &tx1,
- RDPCS_PHY_DP_TX2_DATA_EN, &tx2,
- RDPCS_PHY_DP_TX3_DATA_EN, &tx3);
- s->rdpcs_tx_data_en = tx0 | tx1 << 1 | tx2 << 2 | tx3 << 3;
- }
-}
-
enum signal_type dcn401_get_dig_mode(
struct link_encoder *enc)
{
@@ -419,7 +399,7 @@ void dcn401_setup_ri_pj_check_in_sw_or_hw_mode(
}
static const struct link_encoder_funcs dcn401_link_enc_funcs = {
- .read_state = dcn401_link_encoder_read_state,
+ .read_state = link_enc2_read_state,
.validate_output_with_stream =
dcn30_link_encoder_validate_output_with_stream,
.hw_init = enc401_hw_init,
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
index 689fc817dbc5..62f8f9098b53 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
@@ -28,13 +28,6 @@
#include "dcn30/dcn30_dio_link_encoder.h"
-#define LINK_ENCODER_PHY_STATE_MASK_SH_LIST_DCN401(mask_sh) \
- LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\
- LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\
- LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\
- LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\
- LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh)
-
#define LINK_ENCODER_MASK_SH_LIST_DCN401(mask_sh) \
LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_BE_ENABLE, mask_sh),\
LE_SF(DIG0_DIG_BE_CNTL, DIG_RB_SWITCH_EN, mask_sh),\
@@ -157,7 +150,6 @@ enum signal_type dcn401_get_dig_mode(
struct link_encoder *enc);
bool dcn401_is_dig_enabled(struct link_encoder *enc);
-void dcn401_link_encoder_read_state(struct link_encoder *enc, struct link_enc_state *s);
enum signal_type dcn401_get_dig_mode(struct link_encoder *enc);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
index 1c95d643af14..f3ef5bbfad81 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
@@ -117,8 +117,6 @@ struct link_enc_state {
uint32_t dphy_fec_ready_shadow;
uint32_t dphy_fec_active_status;
uint32_t dp_link_training_complete;
- uint32_t rdpcs_phy_reset;
- uint32_t rdpcs_tx_data_en;
};
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index acc5aa8d777f..34e218bff078 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -307,23 +307,19 @@ static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];
#define link_regs_init(id, phyid) \
LE_DCN401_REG_LIST_RI(id), \
- LE_DCN60_REG_LIST_RI(id), \
- SRI_ARR(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \
- SRI_ARR(RDPCSTX_PHY_CNTL3, RDPCSTX, id)
+ LE_DCN60_REG_LIST_RI(id)
static struct dcn10_link_enc_registers link_enc_regs[4];
static const struct dcn10_link_enc_shift le_shift = {
LINK_ENCODER_MASK_SH_LIST_DCN401(__SHIFT), \
- LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(__SHIFT), \
- LINK_ENCODER_PHY_STATE_MASK_SH_LIST_DCN401(__SHIFT)
+ LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(__SHIFT)
};
static const struct dcn10_link_enc_mask le_mask = {
LINK_ENCODER_MASK_SH_LIST_DCN401(_MASK), \
- LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(_MASK), \
- LINK_ENCODER_PHY_STATE_MASK_SH_LIST_DCN401(_MASK)
+ LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(_MASK)
};
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 06/28] drm/amd/display: Adjust DSC slice calc. policy
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (4 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 05/28] drm/amd/display: Remove DCN401 RDPCS PHY state reads Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 07/28] drm/amd/display: Configure alternate-channel apertures Alex Hung
` (22 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Ilya Bakoulin, Wenjing Liu
From: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
[WHY & HOW]
Need to adjust the DSC slice calculation to reflect the policy change
where given a 1-slice config limit:
- Throughput per slice is limited to the 1-slice limit up to 4 slices
- Throughput per slice is tied to DSC encoder caps for 8+ slices
This is needed to avoid cases where some DSC config can end up exceeding
the 1-slice throughput limit either by itself or with dynamic ODM.
Cc: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c | 31 ++++++++++++++++++-
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 24 +++++++++++++-
.../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c | 1 +
drivers/gpu/drm/amd/display/dc/dsc/dsc.h | 1 +
4 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
index 29082b186134..1c8daa7d46a1 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
@@ -1778,6 +1778,35 @@ static void dcn60_execute_clk_mgr_block_sequence_bls(struct clk_mgr *clk_mgr_bas
dcn60_execute_block_sequence(clk_mgr_base, clk_mgr60->num_block_sequence_steps);
}
+static unsigned int dcn60_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ unsigned int num_clk_levels;
+
+ switch (clk_type) {
+ case CLK_TYPE_DISPCLK:
+ num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+ return dcn60_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DISPCLK) ?
+ clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 :
+ clk_mgr->base.boot_snapshot.dispclk;
+ case CLK_TYPE_DPPCLK:
+ num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dppclk_levels;
+ return dcn60_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DPPCLK) ?
+ clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dppclk_mhz * 1000 :
+ clk_mgr->base.boot_snapshot.dppclk;
+ case CLK_TYPE_DSCCLK:
+ num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+ return dcn60_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DISPCLK) ?
+ clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 / 6 :
+ clk_mgr->base.boot_snapshot.dispclk / 6;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static struct clk_mgr_funcs dcn60_funcs = {
.get_dp_ref_clk_frequency = dcn10_get_dp_ref_freq_khz,
.get_dtb_ref_clk_frequency = dcn60_get_dtb_ref_freq_khz,
@@ -1790,7 +1819,7 @@ static struct clk_mgr_funcs dcn60_funcs = {
.enable_pme_wa = dcn60_enable_pme_wa,
.is_smu_present = dcn60_is_smu_present,
.get_dispclk_from_dentist = NULL,
- .get_max_clock_khz = dcn401_get_max_clock_khz,
+ .get_max_clock_khz = dcn60_get_max_clock_khz,
.override_memory_bandwidth_request = dcn60_override_memory_bandwidth_request,
.get_requested_memory_qos = dcn60_get_requested_memory_qos,
.set_idle_power_optimizations = dcn60_set_idle_power_optimizations,
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index febb6af43827..45ef1f745c7d 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -1057,7 +1057,7 @@ static void build_dsc_enc_caps(
unsigned int max_dscclk_khz;
unsigned int num_dsc;
unsigned int max_odm_combine_factor;
- struct dsc_enc_caps single_dsc_enc_caps;
+ struct dsc_enc_caps single_dsc_enc_caps = {0};
struct dc *dc;
@@ -1082,6 +1082,7 @@ static void build_dsc_enc_caps(
dsc_enc_caps->bpp_increment_div = single_dsc_enc_caps.bpp_increment_div;
dsc_enc_caps->color_formats.raw = single_dsc_enc_caps.color_formats.raw;
dsc_enc_caps->color_depth.raw = single_dsc_enc_caps.color_depth.raw;
+ dsc_enc_caps->single_slice_config_throughput_mps = single_dsc_enc_caps.single_slice_config_throughput_mps;
/* expand per DSC capabilities to global */
max_odm_combine_factor = dc->caps.max_odm_combine_factor;
@@ -1873,6 +1874,27 @@ static bool setup_dsc_config(
min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h);
}
+ /* Increase minimum slice count to meet DSC encoder clock and dynamic ODM limitations.
+ *
+ * Make sure that dynamic ODM can't create a config where there is 1 slice per ODM pipe and
+ * the required 1-slice throughput exceeds single_slice_config_throughput_mps.
+ * E.g. a 2-to-1 ODM config with 4 total slices transitioning to 4-to-1 ODM.
+ *
+ * Also prevent a single-slice non-ODM config where 1-slice throughput exceeds
+ * single_slice_config_throughput_mps.
+ */
+ while (min_slices_h <= max_slices_h && dsc_enc_caps->single_slice_config_throughput_mps) {
+ int pix_clk_per_slice_khz = dsc_div_by_10_round_up(timing->pix_clk_100hz) / min_slices_h;
+ /* Don't care about this condition if there is a minimum of 2 slices per ODM at max split */
+ if (min_slices_h > 4)
+ break;
+ if (min_slices_h <= 4 &&
+ pix_clk_per_slice_khz <= (dsc_enc_caps->single_slice_config_throughput_mps * 1000))
+ break;
+
+ min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h);
+ }
+
/* increase minimum slice count to meet divisibility requirements */
while (pic_width % min_slices_h != 0 && min_slices_h <= max_slices_h) {
min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h);
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 91ec525b11d0..a349a416240d 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
@@ -458,6 +458,7 @@ void dsc60_get_single_enc_caps(struct dsc_enc_caps *dsc_enc_caps, unsigned int m
dsc_enc_caps->color_depth.bits.COLOR_DEPTH_10_BPC = 1;
dsc_enc_caps->color_depth.bits.COLOR_DEPTH_12_BPC = 1;
dsc_enc_caps->max_total_throughput_mps = max_dscclk_khz * 3 / 1000;
+ dsc_enc_caps->single_slice_config_throughput_mps = 340;
dsc_enc_caps->max_slice_width = 5760; /* (including 64 overlap pixels for eDP MSO mode) */
dsc_enc_caps->bpp_increment_div = 16; /* 1/16th of a bit */
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
index cb7b0b1d8686..4f58d0ddbf22 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
@@ -100,6 +100,7 @@ struct dsc_enc_caps {
union dsc_color_formats color_formats;
union dsc_color_depth color_depth;
int32_t max_total_throughput_mps; /* Maximum total throughput with all the slices combined */
+ int32_t single_slice_config_throughput_mps;
int32_t max_slice_width;
uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */
bool is_frl;
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 07/28] drm/amd/display: Configure alternate-channel apertures
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (5 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 06/28] drm/amd/display: Adjust DSC slice calc. policy Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 08/28] drm/amd/display: Avoid closing unowned DDC pins Alex Hung
` (21 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, 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]
Alternate channel P-State switching enables in-frame P-State changes by
streaming scanout from carved DRAM apertures on one memory channel set
while the other is optimized.
[HOW]
Read both aperture regions from IP discovery, translate their
addresses for DMUB and DML2, and populate their base and size fields.
Cc: Sun peng (Leo) Li <sunpeng.li@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_dmub.c | 63 +++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c
index b0325d686b28..614709fe11a6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c
@@ -160,6 +160,68 @@ bool dm_register_dmub_notify_callback(struct amdgpu_device *adev,
}
EXPORT_IF_KUNIT(dm_register_dmub_notify_callback);
+
+/**
+ * dm_get_alt_channel_pstate_switch_aperture - Set the vactive p-state switch apertures.
+ * @adev: amdgpu device containing the discovered apertures
+ * @hw_params: DMUB hardware parameters to populate
+ *
+ * Reads both apertures before populating the DMUB parameters and DML2 config.
+ * Translates their base addresses into MC space for DML2. If either aperture
+ * is unavailable, the feature remains disabled.
+ */
+static void
+dm_get_alt_channel_pstate_switch_aperture(struct amdgpu_device *adev,
+ struct dmub_srv_hw_params *hw_params)
+{
+ static const u32 region_ids[] = {
+ G7_PSTATE_APERTURE1_ID,
+ G7_PSTATE_APERTURE2_ID,
+ };
+ struct mem_reserved_info apertures[ARRAY_SIZE(region_ids)];
+ u64 aperture_mc_bases[ARRAY_SIZE(region_ids)];
+ u32 i;
+ int r;
+
+ /* Region IDs 5 and 6 identify the p-state switch apertures 1 and 2.
+ * Do not publish partial aperture configuration if either lookup fails.
+ */
+ for (i = 0; i < ARRAY_SIZE(region_ids); i++) {
+ r = amdgpu_discovery_get_mem_reserved_region_by_id(adev,
+ region_ids[i], &apertures[i]);
+ if (r) {
+ drm_warn(adev_to_drm(adev),
+ "P-state switching during vactive unavailable: aperture %u lookup failed (%d)\n",
+ region_ids[i], r);
+ return;
+ }
+
+ if (!apertures[i].reserved_region_size ||
+ apertures[i].reserved_region_size >= (0xfffULL << 20)) {
+ drm_warn(adev_to_drm(adev),
+ "P-state switching during vactive unavailable: aperture %u has invalid size\n",
+ region_ids[i]);
+ return;
+ }
+
+ /* DML2 requires the reserved-region base in MC address space. */
+ aperture_mc_bases[i] = apertures[i].reserved_region_start +
+ adev->gmc.fb_start - adev->vm_manager.vram_base_offset;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(region_ids); i++) {
+ hw_params->soc_fb_info.alt_channel_region_base[i] = aperture_mc_bases[i];
+ hw_params->soc_fb_info.alt_channel_region_size[i] =
+ apertures[i].reserved_region_size;
+ /* DML consumes the MC base address bits [47:16]. */
+ adev->dm.dc->dml2_options.alt_ch_cfg.region_base_addr_47_16[i] =
+ (u32)(aperture_mc_bases[i] >> 16);
+ adev->dm.dc->dml2_options.alt_ch_cfg.region_size_bytes[i] =
+ (u32)apertures[i].reserved_region_size;
+ }
+}
+
+
int dm_dmub_hw_init(struct amdgpu_device *adev)
{
const struct dmcub_firmware_header_v1_0 *hdr;
@@ -261,6 +323,7 @@ int dm_dmub_hw_init(struct amdgpu_device *adev)
memset(&hw_params, 0, sizeof(hw_params));
hw_params.soc_fb_info.fb_base = adev->gmc.fb_start;
hw_params.soc_fb_info.fb_offset = adev->vm_manager.vram_base_offset;
+ dm_get_alt_channel_pstate_switch_aperture(adev, &hw_params);
/* backdoor load firmware and trigger dmub running */
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 08/28] drm/amd/display: Avoid closing unowned DDC pins
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (6 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 07/28] drm/amd/display: Configure alternate-channel apertures Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 09/28] drm/amd/display: Support replay frame update interval Alex Hung
` (20 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Mario Limonciello,
Alex Deucher, stable
[WHY]
dal_ddc_open() cleans up pins it acquires on later failures. If the
data-pin open fails, this attempt acquired nothing. If opening the
clock pin or configuring fails, dal_ddc_open() closes the pins it
opened. An extra dal_ddc_close() is unnecessary and unsafe:
GPIO_RESULT_ALREADY_OPENED can mean AUX owns the existing handles,
and closing them here would disrupt AUX.
[HOW]
Remove the extra dal_ddc_close() from the failed-open path.
Cc: Jerry Zuo <jerry.zuo@amd.com>
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../drm/amd/display/dc/link/protocols/link_dp_capability.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index ad1a499b0d9d..c487c5b87dfd 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -2602,12 +2602,8 @@ bool dp_is_sink_present(struct dc_link *link)
* which indicates we need additional delay
*/
- if (dal_ddc_open(ddc, GPIO_MODE_INPUT,
- GPIO_DDC_CONFIG_TYPE_MODE_I2C) != GPIO_RESULT_OK) {
- dal_ddc_close(ddc);
-
+ if (dal_ddc_open(ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C) != GPIO_RESULT_OK)
return present;
- }
/*
* Read GPIO: DP sink is present if both clock and data pins are zero
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 09/28] drm/amd/display: Support replay frame update interval
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (7 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 08/28] drm/amd/display: Avoid closing unowned DDC pins Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 10/28] drm/amd/display: Indicate wait_resp based on FAMS even in disable path Alex Hung
` (19 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Meenakshikumar Somasundaram,
Anthony Koo
From: Meenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
[WHY]
Allow a configurable frame-update cadence while display self-refresh
is active.
[HOW]
Carry the interval in per-panel configuration and Replay copy-settings
data, replacing a separate interval command.
Cc: Anthony Koo <anthony.koo@amd.com>
Signed-off-by: Meenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/dc/dc_types.h | 1 +
drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c | 1 +
drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h | 1 -
3 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 45fa52011a7f..8975f9085daa 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -1351,6 +1351,7 @@ struct dc_panel_config {
unsigned int replay_enable_option;
bool enable_frame_skipping;
bool enable_teams_optimization;
+ uint16_t frame_update_interval;
} psr;
/* ABM */
struct varib {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
index e6adca240ccf..365c428eae72 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
@@ -171,6 +171,7 @@ static bool dmub_replay_copy_settings(struct dmub_replay *dmub,
copy_settings_data->smu_optimizations_en = link->replay_settings.replay_smu_opt_enable;
copy_settings_data->replay_timing_sync_supported = link->replay_settings.config.replay_timing_sync_supported;
copy_settings_data->replay_support_fast_resync_in_ultra_sleep_mode = link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode;
+ copy_settings_data->frame_update_interval = link->panel_config.psr.frame_update_interval;
copy_settings_data->debug.bitfields.enable_ips_visual_confirm = dc->dc->debug.enable_ips_visual_confirm;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
index fa17cd395e5c..cdb4a77f92fd 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h
@@ -41,5 +41,4 @@ struct dmub_replay_funcs {
struct dmub_replay *dmub_replay_create(struct dc_context *ctx);
void dmub_replay_destroy(struct dmub_replay **dmub);
-
#endif /* _DMUB_REPLAY_H_ */
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 10/28] drm/amd/display: Indicate wait_resp based on FAMS even in disable path
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (8 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 09/28] drm/amd/display: Support replay frame update interval Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 11/28] drm/amd/display: Update Rounding For VM stage groups Alex Hung
` (18 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Alvin Lee, Wenjing Liu
From: Alvin Lee <Alvin.Lee2@amd.com>
[WHAT]
The "disable" path for indicate PSTATE status can be triggered due to
disabling alt-ch, but keeping everything else enabled (UCLK, FAMS).
In this case we must assign the wait_resp flag based on FAMS instead
of hardcoding to false in the disable path.
Cc: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
index 1c8daa7d46a1..98d146bc25c0 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
@@ -1458,7 +1458,9 @@ static unsigned int dcn60_build_bandwidth_clocks_block_sequence_with_action(
!action->alt_ch.disable
&& (action->alt_ch.enable
|| clk_mgr_base->clks.alt_ch_pstate_switch);
- block_sequence[num_steps].params.indicate_pstate_status_params.wait_resp = false;
+ block_sequence[num_steps].params.indicate_pstate_status_params.wait_resp =
+ action->fams.enable
+ || clk_mgr_base->clks.fw_based_mclk_switching;
block_sequence[num_steps].func = CLK_MGR60_INDICATE_PSTATE_STATUS;
num_steps++;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 11/28] drm/amd/display: Update Rounding For VM stage groups
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (9 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 10/28] drm/amd/display: Indicate wait_resp based on FAMS even in disable path Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 12/28] drm/amd/display: Fix unadvertised mode detection Alex Hung
` (17 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Austin Zheng, Dillon Varone
From: Austin Zheng <Austin.Zheng@amd.com>
[WHY & HOW]
Value to be ceiled should be casted to properly ceil the calculated value.
Otherwise a value < 1 will get truncated to 0 and won't get ceiled.
Cc: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Austin Zheng <Austin.Zheng@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.c
index 262b8e098343..09cfb5046c81 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.c
@@ -4893,7 +4893,7 @@ void dcn5_calculate_vm_group_and_request_times(
num_group_per_lower_vm_stage_pref = num_group_per_lower_vm_stage;
if (display_cfg->plane_descriptors[k].tdlut.setup_for_tdlut && display_cfg->gpuvm_enable) {
- num_group_per_lower_vm_stage_pref += (unsigned int) math_ceil2(tdlut_pte_bytes_per_frame[k] / vm_group_bytes[k], 1);
+ num_group_per_lower_vm_stage_pref += (unsigned int) math_ceil2((double) tdlut_pte_bytes_per_frame[k] / (double) vm_group_bytes[k], 1);
if (display_cfg->gpuvm_max_page_table_levels >= 2)
num_group_per_lower_vm_stage_pref += 1; // tdpe0 group
}
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 12/28] drm/amd/display: Fix unadvertised mode detection
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (10 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 11/28] drm/amd/display: Update Rounding For VM stage groups Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 13/28] drm/amd/display: Parameterize FCLK/PPT/Temp Read P-State Optimizer Alex Hung
` (16 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen
From: Fangzhi Zuo <jerry.zuo@amd.com>
[WHY]
The advertised mode list moves between probed_modes and modes during
mode validation. Checking only one list can misclassify valid modes or
allow generated FreeSync modes to be added more than once.
[HOW]
Make is_duplicate_mode() search both connector->modes and
connector->probed_modes so it works before and after DRM transfers
probed modes. Update the KUnit fixtures to use the advertised modes
list.
Fixes: ed82b939ccd1 ("drm/amd/display: warn on unadvertised modes without scaling")
Cc: Roman Li <roman.li@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_connector.c | 5 +++
.../tests/amdgpu_dm_connector_test.c | 38 +++++++++++++++++--
2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index bc5745a5ba37..37b41c887ede 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -1407,6 +1407,11 @@ STATIC_IFN_KUNIT bool is_duplicate_mode(struct amdgpu_dm_connector *aconnector,
return true;
}
+ list_for_each_entry(m, &aconnector->base.modes, head) {
+ if (drm_mode_equal(m, mode))
+ return true;
+ }
+
return false;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
index acde20241f43..7965a221e0e9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
@@ -1135,6 +1135,7 @@ static void dm_test_is_duplicate_mode_empty_list(struct kunit *test)
aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ INIT_LIST_HEAD(&aconnector->base.modes);
INIT_LIST_HEAD(&aconnector->base.probed_modes);
mode.hdisplay = 1920;
mode.vdisplay = 1080;
@@ -1155,6 +1156,34 @@ static void dm_test_is_duplicate_mode_match(struct kunit *test)
aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ INIT_LIST_HEAD(&aconnector->base.modes);
+ INIT_LIST_HEAD(&aconnector->base.probed_modes);
+ existing.hdisplay = 1920;
+ existing.vdisplay = 1080;
+ existing.clock = 148500;
+ list_add_tail(&existing.head, &aconnector->base.modes);
+
+ candidate.hdisplay = 1920;
+ candidate.vdisplay = 1080;
+ candidate.clock = 148500;
+
+ KUNIT_EXPECT_TRUE(test, is_duplicate_mode(aconnector, &candidate));
+}
+
+/**
+ * dm_test_is_duplicate_mode_probed_match - Test probed mode duplicate match
+ * @test: The KUnit test context
+ */
+static void dm_test_is_duplicate_mode_probed_match(struct kunit *test)
+{
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_display_mode existing = {};
+ struct drm_display_mode candidate = {};
+
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+
+ INIT_LIST_HEAD(&aconnector->base.modes);
INIT_LIST_HEAD(&aconnector->base.probed_modes);
existing.hdisplay = 1920;
existing.vdisplay = 1080;
@@ -1182,10 +1211,11 @@ static void dm_test_is_duplicate_mode_no_match(struct kunit *test)
KUNIT_ASSERT_NOT_NULL(test, aconnector);
INIT_LIST_HEAD(&aconnector->base.probed_modes);
+ INIT_LIST_HEAD(&aconnector->base.modes);
existing.hdisplay = 1920;
existing.vdisplay = 1080;
existing.clock = 148500;
- list_add_tail(&existing.head, &aconnector->base.probed_modes);
+ list_add_tail(&existing.head, &aconnector->base.modes);
candidate.hdisplay = 2560;
candidate.vdisplay = 1440;
@@ -1207,12 +1237,13 @@ static void dm_test_is_duplicate_mode_same_size_different_clock(struct kunit *te
aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, aconnector);
-
INIT_LIST_HEAD(&aconnector->base.probed_modes);
+
+ INIT_LIST_HEAD(&aconnector->base.modes);
existing.hdisplay = 1920;
existing.vdisplay = 1080;
existing.clock = 148500;
- list_add_tail(&existing.head, &aconnector->base.probed_modes);
+ list_add_tail(&existing.head, &aconnector->base.modes);
candidate.hdisplay = 1920;
candidate.vdisplay = 1080;
@@ -10096,6 +10127,7 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
/* is_duplicate_mode */
KUNIT_CASE(dm_test_is_duplicate_mode_empty_list),
KUNIT_CASE(dm_test_is_duplicate_mode_match),
+ KUNIT_CASE(dm_test_is_duplicate_mode_probed_match),
KUNIT_CASE(dm_test_is_duplicate_mode_no_match),
KUNIT_CASE(dm_test_is_duplicate_mode_same_size_different_clock),
/* amdgpu_dm_get_encoder_crtc_mask */
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 13/28] drm/amd/display: Parameterize FCLK/PPT/Temp Read P-State Optimizer
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (11 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 12/28] drm/amd/display: Fix unadvertised mode detection Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 14/28] drm/amd/display: Reset DET of HUBPs without a plane before outstanding updates Alex Hung
` (15 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Austin Zheng, Dillon Varone
From: Austin Zheng <Austin.Zheng@amd.com>
[WHY & HOW]
This optimizer is used to ensure mandatory pstates are supported.
So any other p-states can be passed in.
e.g.
UCLK p-state optimization can be done in this optimizer for a more
aggressive optimization.
Note that this will make the separate UCLK optimizer redundant.
Cc: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Austin Zheng <Austin.Zheng@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c | 25 ++++++++++++-------
.../src/inc/dml2_internal_shared_types.h | 3 +++
2 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c
index 40dcaa6588ff..c4db8ff3ee30 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c
@@ -1707,9 +1707,21 @@ static void dml2_pmo_dcn6_stage_optimizer_fclk_ppt_temp_read_pstate_init(
struct dml2_pmo_stage_optimizer *stage, struct dml2_optimization_worksheet *worksheet)
{
DML_LOG_COMP_IF_ENTER();
+
+ static const enum dml2_pstate_type pstate_type_list[] = {
+ dml2_pstate_type_fclk,
+ dml2_pstate_type_ppt,
+ dml2_pstate_type_temp_read,
+ };
+
worksheet->fclk_ppt_temp_read_pstate.index = 0;
memset(&stage->func_locals->fclk_ppt_temp_read_pstate_optimize, 0,
sizeof(struct dml2_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_locals));
+ memcpy(worksheet->fclk_ppt_temp_read_pstate.pstate_type_list, pstate_type_list,
+ sizeof(pstate_type_list));
+ worksheet->fclk_ppt_temp_read_pstate.num_pstate_types = ARRAY_SIZE(pstate_type_list);
+
+ DML_ASSERT_MSG(worksheet->fclk_ppt_temp_read_pstate.num_pstate_types < dml2_pstate_type_count, "Too many pstate types defined");
DML_LOG_COMP_IF_EXIT();
}
@@ -1717,11 +1729,6 @@ static bool dml2_pmo_dcn6_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_nex
struct dml2_pmo_stage_optimizer *stage, struct dml2_optimization_worksheet *worksheet)
{
const struct dml2_pmo_instance *pmo = stage->pmo;
- const enum dml2_pstate_type pstate_type_list[3] = {
- dml2_pstate_type_fclk,
- dml2_pstate_type_ppt,
- dml2_pstate_type_temp_read,
- };
struct dml2_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_locals *l
= &stage->func_locals->fclk_ppt_temp_read_pstate_optimize;
const struct dml2_display_cfg *display_config = worksheet->orig_dispcfg;
@@ -1739,9 +1746,9 @@ static bool dml2_pmo_dcn6_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_nex
if (display_config->overrides.all_streams_blanked)
goto exit;
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < worksheet->fclk_ppt_temp_read_pstate.num_pstate_types; i++) {
dcn6_get_params_for_pstate_type(pmo, worksheet,
- pstate_type_list[i],
+ worksheet->fclk_ppt_temp_read_pstate.pstate_type_list[i],
&l->pstate_allow_delay_us,
&l->pstate_blackout_us,
&l->pstate_watermark_us);
@@ -1761,7 +1768,7 @@ static bool dml2_pmo_dcn6_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_nex
dcn6_build_pstate_meta_per_stream(display_config,
pmo->ip_caps,
worksheet,
- pstate_type_list[i],
+ worksheet->fclk_ppt_temp_read_pstate.pstate_type_list[i],
l->pstate_watermark_us,
l->pstate_blackout_us,
l->pstate_allow_delay_us,
@@ -1772,7 +1779,7 @@ static bool dml2_pmo_dcn6_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_nex
/* always update the worksheet with latest requirements */
if (dcn6_update_worksheet_for_pstate_admissibility(worksheet,
- l->per_stream_pstate_meta, pstate_type_list[i])) {
+ l->per_stream_pstate_meta, worksheet->fclk_ppt_temp_read_pstate.pstate_type_list[i])) {
modified = true;
DML_LOG_VERBOSE("fclk_ppt_temp_read pstate not admissible with current worksheet, adjusting the reserved vblank time\n");
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
index 6f527760071c..fab9d149b3de 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
@@ -644,6 +644,9 @@ struct dml2_optimization_worksheet {
struct {
unsigned int index;
+
+ enum dml2_pstate_type pstate_type_list[dml2_pstate_type_count];
+ unsigned int num_pstate_types;
} fclk_ppt_temp_read_pstate;
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 14/28] drm/amd/display: Reset DET of HUBPs without a plane before outstanding updates
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (12 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 13/28] drm/amd/display: Parameterize FCLK/PPT/Temp Read P-State Optimizer Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 15/28] drm/amd/display: Decouple FAMS2 config update from dc/dc_state and add BLS opcode Alex Hung
` (14 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Roman Li, Dillon Varone,
Mario Limonciello, Alex Deucher, stable
From: Roman Li <Roman.Li@amd.com>
[WHY]
DC asserts with:
WARNING: dc/hubbub/dcn401/dcn401_hubbub.c at dcn401_program_compbuf_segments
Call Trace:
<TASK>
dcn401_program_outstanding_updates+0x36/0x60 [amdgpu]
hwss_process_outstanding_hw_updates+0x33/0x40 [amdgpu]
commit_planes_for_stream+0x171f/0x1ff0 [amdgpu]
dc_update_state_execute+0xaa/0x170 [amdgpu]
dc_update_planes_and_stream+0x42/0x70 [amdgpu]
amdgpu_dm_atomic_commit_tail+0x16a9/0x4020 [amdgpu]
commit_tail+0xc3/0x1b0 [drm_kms_helper]
The DET left by the VBIOS on a HUBP without a plane can be larger than
the DET planned for the new state. The compbuf is sized for the planned
DET, so DET + compbuf can exceed the CRB size. Programming the compbuf
then triggers the ASSERT and sets CONFIG_ERROR in hardware.
[HOW]
Release the DET of HUBPs without a plane before the compbuf is
programmed.
Add hwss_reset_unused_det() and call it in the commit and flip paths,
to cover both seamless and non-seamless boots.
Fixes: 7a1eb6680939 ("drm/amd/display: Perform outstanding programming on full updates")
Cc: Dillon Varone <dillon.varone@amd.com>
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: Roman Li <Roman.Li@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++-
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 31 +++++++++++++++++++
.../drm/amd/display/dc/hwss/hw_sequencer.h | 3 ++
3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index ae5f03a73132..e73666e46557 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2551,6 +2551,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
* update pending complete before optimizing bandwidth.
*/
hwss_wait_for_odm_update_pending_complete(dc, context);
+ /* No DET may stay allocated to a HUBP without a plane (e.g. left over from VBIOS) */
+ hwss_reset_unused_det(dc, context);
/* pplib is notified if disp_num changed */
dc->hwss.optimize_bandwidth(dc, context);
/* Need to do otg sync again as otg could be out of sync due to otg
@@ -4981,8 +4983,10 @@ static void commit_planes_for_stream(struct dc *dc,
dc_exit_ips_for_hw_access(dc);
dc_z10_restore(dc);
- if (update_type == UPDATE_TYPE_FULL && dc->optimized_required)
+ if (update_type == UPDATE_TYPE_FULL && dc->optimized_required) {
+ hwss_reset_unused_det(dc, dc->current_state);
hwss_process_outstanding_hw_updates(dc, dc->current_state);
+ }
if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming)
dc->res_pool->funcs->prepare_mcache_programming(dc, context);
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 415ad6ddb740..3c5ffa7073f5 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
@@ -3140,6 +3140,37 @@ void hwss_wait_for_odm_update_pending_complete(struct dc *dc, struct dc_state *c
hwss_wait_for_all_blank_complete(dc, context);
}
+void hwss_reset_unused_det(struct dc *dc, struct dc_state *context)
+{
+ struct hubbub *hubbub = dc->res_pool->hubbub;
+ unsigned int i, j;
+
+ if (!hubbub || !hubbub->funcs->program_det_segments)
+ return;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct hubp *hubp = dc->res_pool->hubps[i];
+ bool hubp_in_use = false;
+
+ if (!hubp)
+ continue;
+
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[j];
+
+ /* A plane-less pipe renders from the DPG, its HUBP (assigned with the stream) needs no DET */
+ if (pipe->plane_state && pipe->plane_res.hubp &&
+ pipe->plane_res.hubp->inst == hubp->inst) {
+ hubp_in_use = true;
+ break;
+ }
+ }
+
+ if (!hubp_in_use)
+ hubbub->funcs->program_det_segments(hubbub, hubp->inst, 0);
+ }
+}
+
void hwss_wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
{
int i;
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 3ee6129a388d..e8ffae05add8 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -2059,6 +2059,9 @@ void hwss_wait_for_odm_update_pending_complete(struct dc *dc,
void hwss_wait_for_no_pipes_pending(struct dc *dc,
struct dc_state *context);
+void hwss_reset_unused_det(struct dc *dc,
+ struct dc_state *context);
+
void hwss_wait_for_outstanding_hw_updates(struct dc *dc,
struct dc_state *dc_context);
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 15/28] drm/amd/display: Decouple FAMS2 config update from dc/dc_state and add BLS opcode
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (13 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 14/28] drm/amd/display: Reset DET of HUBPs without a plane before outstanding updates Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 16/28] drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.4 Alex Hung
` (13 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Rafal Ostrowski, Alvin Lee,
Rafal Ostrowski
From: Rafal Ostrowski <Rafal.Ostrowski@amd.com>
[WHY]
The FAMS2 config path (dcn401_fams2_update_config down to
dc_dmub_srv_cmd_list_queue_execute) took dc and dc_state, so it could
not be turned into a BLS opcode whose executor must not touch dc or
dc_state.
[HOW]
- Add struct dc_dmub_fams2_config_data and make
dc_dmub_srv_fams2_update_config() take (dc_dmub_srv, data); the RB and
IB senders no longer read dc or dc_state. The per-stream arrays are
pointers into dc_state to keep union block_sequence_params small.
- Snapshot disable_timeout and enable_dmu_recovery into struct
dc_dmub_srv so queue_execute, wait_for_idle and handle_failure no
longer read ctx->dc->debug.
- Split the DCN4.01 hwseq code: dcn401_fams2_build_update_config() fills
the data from dc/dc_state and replaces hwss.fams2_update_config for
DCN4.01/4.2/6.0. Direct callers (prepare/optimize_bandwidth and
hardware_release) build the data and send it with
dc_dmub_srv_fams2_update_config().
- Add the DMUB_FAMS2_UPDATE_CONFIG block sequence opcode:
hwss_add_dmub_fams2_update_config() builds the data and
hwss_dmub_fams2_update_config() sends it. Use it, bracketed by
hwss_add_dmub_hw_control_lock_fast(), in
dcn401_prepare_bandwidth_sequence() (disable) and
dcn401_optimize_bandwidth_sequence() (enable).
Cc: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Rafal Ostrowski <rafal.ostrowski@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 30 +++++
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 113 +++++++++---------
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 27 ++++-
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 64 ++++++----
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 4 +-
.../amd/display/dc/hwss/dcn401/dcn401_init.c | 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 | 17 ++-
9 files changed, 177 insertions(+), 84 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 3c5ffa7073f5..88262cf86598 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
@@ -88,6 +88,33 @@ void hwss_dmub_hw_control_lock_fast(union block_sequence_params *params)
dmub_hw_lock_mgr_inbox0_cmd(p->dmub_srv, p->command);
}
+void hwss_add_dmub_fams2_update_config(struct block_sequence_state *seq_state,
+ struct dc *dc, struct dc_state *context, bool enable)
+{
+ struct dmub_fams2_update_config_params *params;
+
+ if (!seq_state || !seq_state->steps || !seq_state->num_steps || !dc || !dc->ctx ||
+ !dc->hwss.fams2_build_update_config ||
+ *seq_state->num_steps >= MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+ 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_fams2_update_config_params;
+ if (!dc->hwss.fams2_build_update_config(dc, context, enable, ¶ms->data))
+ return;
+
+ params->dmub_srv = dc->ctx->dmub_srv;
+ seq_state->steps[(*seq_state->num_steps)++].func = DMUB_FAMS2_UPDATE_CONFIG;
+}
+
+void hwss_dmub_fams2_update_config(union block_sequence_params *params)
+{
+ struct dmub_fams2_update_config_params *p = ¶ms->dmub_fams2_update_config_params;
+
+ dc_dmub_srv_fams2_update_config(p->dmub_srv, &p->data);
+}
+
#define MAX_NUM_MCACHE 8
/* used as index in array of black_color_format */
@@ -2198,6 +2225,9 @@ void hwss_execute_sequence(struct dc *dc,
case HUBBUB_PROGRAM_COMPBUF_SEGMENTS:
hwss_hubbub_program_compbuf_segments(params);
break;
+ case DMUB_FAMS2_UPDATE_CONFIG:
+ hwss_dmub_fams2_update_config(params);
+ break;
default:
ASSERT(false);
break;
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 f1a0225bbf84..323e8bec23dc 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -46,12 +46,14 @@ static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
{
dc_srv->dmub = dmub;
dc_srv->ctx = dc->ctx;
+ dc_srv->disable_timeout = dc->debug.disable_timeout;
+ dc_srv->enable_dmu_recovery = dc->debug.enable_dmu_recovery;
}
static void dc_dmub_srv_handle_failure(struct dc_dmub_srv *dc_dmub_srv)
{
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
- if (dc_dmub_srv->ctx->dc->debug.enable_dmu_recovery)
+ if (dc_dmub_srv->enable_dmu_recovery)
dm_helpers_dmu_timeout(dc_dmub_srv->ctx);
}
@@ -92,7 +94,7 @@ bool dc_dmub_srv_wait_for_pending(struct dc_dmub_srv *dc_dmub_srv)
do {
status = dmub_srv_wait_for_pending(dmub, DMUB_CMD_DEFAULT_MAX_WAIT_US);
- } while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
+ } while (dc_dmub_srv->disable_timeout && status != DMUB_STATUS_OK);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
@@ -162,7 +164,7 @@ static bool dc_dmub_srv_reg_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_s
/* confirm no messages pending */
do {
status = dmub_srv_wait_for_idle(dmub, timeout_us);
- } while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
+ } while (dc_dmub_srv->disable_timeout && status != DMUB_STATUS_OK);
/* queue command */
if (status == DMUB_STATUS_OK)
@@ -218,7 +220,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
do {
status = dmub_srv_wait_for_inbox_free(dmub, timeout_us, count - i);
- } while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
+ } while (dc_dmub_srv->disable_timeout && status != DMUB_STATUS_OK);
/* Requeue the command. */
status = dmub_srv_fb_cmd_queue(dmub, &cmd_list[i]);
@@ -333,7 +335,7 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) {
do {
status = dmub_srv_wait_for_idle(dmub, timeout_us);
- } while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
+ } while (dc_dmub_srv->disable_timeout && status != DMUB_STATUS_OK);
if (status != DMUB_STATUS_OK) {
DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
@@ -1359,7 +1361,7 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait)
dc_ctx = dc_dmub_srv->ctx;
if (wait) {
- if (dc_dmub_srv->ctx->dc->debug.disable_timeout) {
+ if (dc_dmub_srv->disable_timeout) {
do {
status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 500000);
} while (status != DMUB_STATUS_OK);
@@ -1853,11 +1855,10 @@ bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_com
return result;
}
-static void dc_dmub_srv_rb_based_fams2_update_config(struct dc *dc,
- struct dc_state *context,
- bool enable)
+static void dc_dmub_srv_rb_based_fams2_update_config(struct dc_dmub_srv *dc_dmub_srv,
+ const struct dc_dmub_fams2_config_data *data)
{
- uint32_t num_cmds = 1;
+ uint32_t cmd_count = 1;
uint32_t i;
union dmub_rb_cmd cmd[2 * MAX_STREAMS + 1];
struct dmub_rb_cmd_fams2 *global_cmd = &cmd[0].fams2_config;
@@ -1869,19 +1870,21 @@ static void dc_dmub_srv_rb_based_fams2_update_config(struct dc *dc,
global_cmd->header.payload_bytes =
sizeof(struct dmub_rb_cmd_fams2) - sizeof(struct dmub_cmd_header);
- if (enable) {
+ if (data->enable) {
/* send global configuration parameters */
- memcpy(&global_cmd->config.global, &context->bw_ctx.bw.dcn.fams2_global_config, sizeof(struct dmub_cmd_fams2_global_config));
+ memcpy(&global_cmd->config.global, &data->global, sizeof(struct dmub_cmd_fams2_global_config));
/* copy static feature configuration overrides */
- global_cmd->config.global.features.bits.enable_stall_recovery = dc->debug.fams2_config.bits.enable_stall_recovery;
- global_cmd->config.global.features.bits.enable_debug = dc->debug.fams2_config.bits.enable_debug;
- global_cmd->config.global.features.bits.enable_offload_flip = dc->debug.fams2_config.bits.enable_offload_flip;
+ global_cmd->config.global.features.bits.enable_stall_recovery =
+ data->features.bits.enable_stall_recovery;
+ global_cmd->config.global.features.bits.enable_debug = data->features.bits.enable_debug;
+ global_cmd->config.global.features.bits.enable_offload_flip = data->features.bits.enable_offload_flip;
/* construct per-stream configs */
- for (i = 0; i < context->bw_ctx.bw.dcn.fams2_global_config.num_streams; i++) {
+ for (i = 0; i < data->global.num_streams; i++) {
struct dmub_rb_cmd_fams2 *stream_base_cmd = &cmd[i+1].fams2_config;
- struct dmub_rb_cmd_fams2 *stream_sub_state_cmd = &cmd[i+1+context->bw_ctx.bw.dcn.fams2_global_config.num_streams].fams2_config;
+ struct dmub_rb_cmd_fams2 *stream_sub_state_cmd =
+ &cmd[i+1+data->global.num_streams].fams2_config;
/* configure command header */
stream_base_cmd->header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
@@ -1896,38 +1899,37 @@ static void dc_dmub_srv_rb_based_fams2_update_config(struct dc *dc,
stream_sub_state_cmd->header.multi_cmd_pending = 1;
/* copy stream static base state */
memcpy(&stream_base_cmd->config,
- &context->bw_ctx.bw.dcn.fams2_stream_base_params[i],
+ &data->stream_base[i],
sizeof(union dmub_cmd_fams2_config));
/* copy stream static sub state */
memcpy(&stream_sub_state_cmd->config,
- &context->bw_ctx.bw.dcn.fams2_stream_sub_params[i],
+ &data->stream_sub[i],
sizeof(union dmub_cmd_fams2_config));
/* temp override */
- stream_base_cmd->config.stream_v1.base.config.bits.imm_restore_drr = dc->debug.fams2_imm_restore_drr;
+ stream_base_cmd->config.stream_v1.base.config.bits.imm_restore_drr = data->imm_restore_drr;
}
}
/* apply feature configuration based on current driver state */
- global_cmd->config.global.features.bits.enable_visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2;
- global_cmd->config.global.features.bits.enable = enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
- global_cmd->config.global.features.bits.enable_ppt_check = dc->debug.fams2_config.bits.enable_ppt_check;
+ global_cmd->config.global.features.bits.enable_visual_confirm = data->visual_confirm;
+ global_cmd->config.global.features.bits.enable = data->enable && data->global.features.bits.enable;
+ global_cmd->config.global.features.bits.enable_ppt_check = data->features.bits.enable_ppt_check;
- if (enable) {
+ if (data->enable) {
/* set multi pending for global, and unset for last stream cmd */
global_cmd->header.multi_cmd_pending = 1;
- cmd[2 * context->bw_ctx.bw.dcn.fams2_global_config.num_streams].fams2_config.header.multi_cmd_pending = 0;
- num_cmds += 2 * context->bw_ctx.bw.dcn.fams2_global_config.num_streams;
+ cmd[2 * data->global.num_streams].fams2_config.header.multi_cmd_pending = 0;
+ cmd_count += 2 * data->global.num_streams;
}
- dm_execute_dmub_cmd_list(dc->ctx, num_cmds, cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ dm_execute_dmub_cmd_list(dc_dmub_srv->ctx, cmd_count, cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
-static void dc_dmub_srv_ib_based_fams2_update_config(struct dc *dc,
- struct dc_state *context,
- bool enable)
+static void dc_dmub_srv_ib_based_fams2_update_config(struct dc_dmub_srv *dc_dmub_srv,
+ const struct dc_dmub_fams2_config_data *data)
{
- struct dmub_fams2_config_v2 *config = (struct dmub_fams2_config_v2 *)dc->ctx->dmub_srv->dmub->ib_mem_gart.cpu_addr;
+ struct dmub_fams2_config_v2 *config = (struct dmub_fams2_config_v2 *)dc_dmub_srv->dmub->ib_mem_gart.cpu_addr;
union dmub_rb_cmd cmd;
uint32_t i;
@@ -1937,51 +1939,54 @@ static void dc_dmub_srv_ib_based_fams2_update_config(struct dc *dc,
cmd.ib_fams2_config.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
cmd.ib_fams2_config.header.sub_type = DMUB_CMD__FAMS2_IB_CONFIG;
- cmd.ib_fams2_config.ib_data.src.quad_part = dc->ctx->dmub_srv->dmub->ib_mem_gart.gpu_addr;
+ cmd.ib_fams2_config.ib_data.src.quad_part = dc_dmub_srv->dmub->ib_mem_gart.gpu_addr;
cmd.ib_fams2_config.ib_data.size = sizeof(*config);
- if (enable) {
+ if (data->enable) {
/* send global configuration parameters */
- memcpy(&config->global, &context->bw_ctx.bw.dcn.fams2_global_config,
+ memcpy(&config->global, &data->global,
sizeof(struct dmub_cmd_fams2_global_config));
/* copy static feature configuration overrides */
- 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;
+ config->global.features.bits.enable_stall_recovery = data->features.bits.enable_stall_recovery;
+ config->global.features.bits.enable_offload_flip = data->features.bits.enable_offload_flip;
+ config->global.features.bits.enable_debug = data->features.bits.enable_debug;
+ config->global.features.bits.alternate_channel_workaround =
+ data->features.bits.alternate_channel_workaround;
/* construct per-stream configs */
- for (i = 0; i < context->bw_ctx.bw.dcn.fams2_global_config.num_streams; i++) {
+ for (i = 0; i < data->global.num_streams; i++) {
/* copy stream static base state */
memcpy(&config->stream_v1[i].base,
- &context->bw_ctx.bw.dcn.fams2_stream_base_params[i],
+ &data->stream_base[i],
sizeof(config->stream_v1[i].base));
/* copy stream static sub-state */
memcpy(&config->stream_v1[i].sub_state,
- &context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[i],
+ &data->stream_sub_v2[i],
sizeof(config->stream_v1[i].sub_state));
}
}
- config->global.features.bits.enable_visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2;
- config->global.features.bits.enable = enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
- config->global.features.bits.enable_ppt_check = dc->debug.fams2_config.bits.enable_ppt_check;
+ config->global.features.bits.enable_visual_confirm = data->visual_confirm;
+ config->global.features.bits.enable = data->enable && data->global.features.bits.enable;
+ config->global.features.bits.enable_ppt_check = data->features.bits.enable_ppt_check;
- dmub_srv_flush_buffer_mem(dc->ctx->dmub_srv->dmub, &dc->ctx->dmub_srv->dmub->ib_mem_gart);
+ dmub_srv_flush_buffer_mem(dc_dmub_srv->dmub, &dc_dmub_srv->dmub->ib_mem_gart);
- dm_execute_dmub_cmd_list(dc->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ dm_execute_dmub_cmd_list(dc_dmub_srv->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
-void dc_dmub_srv_fams2_update_config(struct dc *dc,
- struct dc_state *context,
- bool enable)
+void dc_dmub_srv_fams2_update_config(struct dc_dmub_srv *dc_dmub_srv,
+ const struct dc_dmub_fams2_config_data *data)
{
- if (dc->debug.fams_version.major == 2)
- dc_dmub_srv_rb_based_fams2_update_config(dc, context, enable);
- if (dc->debug.fams_version.major == 3)
- dc_dmub_srv_ib_based_fams2_update_config(dc, context, enable);
+ if (!dc_dmub_srv || !dc_dmub_srv->dmub)
+ return;
+
+ if (data->fams_version_major == 2)
+ dc_dmub_srv_rb_based_fams2_update_config(dc_dmub_srv, data);
+ if (data->fams_version_major == 3)
+ dc_dmub_srv_ib_based_fams2_update_config(dc_dmub_srv, data);
}
void dc_dmub_srv_fams2_drr_update(struct dc *dc,
@@ -2023,7 +2028,7 @@ void dc_dmub_srv_fams2_passthrough_flip(
int num_cmds = 0;
struct dc_stream_status *stream_status = dc_stream_get_status(stream);
- if (surface_count <= 0 || stream_status == NULL)
+ if (surface_count <= 0 || stream_status == NULL || !dc->ctx->dmub_srv)
return;
memset(cmds, 0, sizeof(union dmub_rb_cmd) * MAX_PLANES);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
index 684b66dc9771..b3d6279cbc15 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -53,6 +53,8 @@ struct dc_dmub_srv {
bool idle_allowed;
bool needs_idle_wake;
bool cursor_offload_enabled;
+ bool disable_timeout;
+ bool enable_dmu_recovery;
};
bool dc_dmub_srv_wait_for_pending(struct dc_dmub_srv *dc_dmub_srv);
@@ -198,9 +200,28 @@ bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned in
bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code,
uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type);
-void dc_dmub_srv_fams2_update_config(struct dc *dc,
- struct dc_state *context,
- bool enable);
+/**
+ * struct dc_dmub_fams2_config_data - Inputs of the FAMS2 config command.
+ *
+ * Filled by the caller from dc and dc_state, so that
+ * dc_dmub_srv_fams2_update_config() needs neither of them.
+ * Note: The stream arrays point into dc_state to keep union block_sequence_params
+ * small; dc_state must outlive the command.
+ */
+struct dc_dmub_fams2_config_data {
+ unsigned int fams_version_major;
+ union dmub_fams2_global_feature_config features;
+ bool imm_restore_drr;
+ bool visual_confirm;
+ bool enable;
+ struct dmub_cmd_fams2_global_config global;
+ const union dmub_cmd_fams2_config *stream_base;
+ const union dmub_cmd_fams2_config *stream_sub;
+ const union dmub_fams2_stream_static_sub_state_v2 *stream_sub_v2;
+};
+
+void dc_dmub_srv_fams2_update_config(struct dc_dmub_srv *dc_dmub_srv,
+ const struct dc_dmub_fams2_config_data *data);
void dc_dmub_srv_fams2_drr_update(struct dc *dc,
uint32_t tg_inst,
uint32_t vtotal_min,
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 09692fc817f9..508749496826 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
@@ -1464,8 +1464,11 @@ void dcn401_prepare_bandwidth(struct dc *dc,
}
if (dc->debug.fams2_config.bits.enable) {
+ struct dc_dmub_fams2_config_data fams2_data;
+
dcn401_dmub_hw_control_lock(dc, context, true);
- dcn401_fams2_update_config(dc, context, false);
+ if (dcn401_fams2_build_update_config(dc, context, false, &fams2_data))
+ dc_dmub_srv_fams2_update_config(dc->ctx->dmub_srv, &fams2_data);
dcn401_dmub_hw_control_lock(dc, context, false);
}
@@ -1518,9 +1521,9 @@ void dcn401_prepare_bandwidth_sequence(struct dc *dc,
}
if (dc->debug.fams2_config.bits.enable) {
- dcn401_dmub_hw_control_lock(dc, context, true);
- dcn401_fams2_update_config(dc, context, false);
- dcn401_dmub_hw_control_lock(dc, context, false);
+ hwss_add_dmub_hw_control_lock_fast(seq_state, dc, true);
+ hwss_add_dmub_fams2_update_config(seq_state, dc, context, false);
+ hwss_add_dmub_hw_control_lock_fast(seq_state, dc, false);
}
if (p_state_change_support != context->bw_ctx.bw.dcn.clk.p_state_change_support)
@@ -1536,8 +1539,11 @@ void dcn401_optimize_bandwidth(
/* enable fams2 if needed */
if (dc->debug.fams2_config.bits.enable) {
+ struct dc_dmub_fams2_config_data fams2_data;
+
dcn401_dmub_hw_control_lock(dc, context, true);
- dcn401_fams2_update_config(dc, context, true);
+ if (dcn401_fams2_build_update_config(dc, context, true, &fams2_data))
+ dc_dmub_srv_fams2_update_config(dc->ctx->dmub_srv, &fams2_data);
dcn401_dmub_hw_control_lock(dc, context, false);
}
@@ -1594,9 +1600,9 @@ void dcn401_optimize_bandwidth_sequence(struct dc *dc,
/* enable fams2 if needed */
if (dc->debug.fams2_config.bits.enable) {
- dcn401_dmub_hw_control_lock(dc, context, true);
- dcn401_fams2_update_config(dc, context, true);
- dcn401_dmub_hw_control_lock(dc, context, false);
+ hwss_add_dmub_hw_control_lock_fast(seq_state, dc, true);
+ hwss_add_dmub_fams2_update_config(seq_state, dc, context, true);
+ hwss_add_dmub_hw_control_lock_fast(seq_state, dc, false);
}
hwss_add_hubbub_program_watermarks(seq_state, dc, hubbub,
@@ -1653,20 +1659,34 @@ bool dcn401_is_dmub_hw_lock_supported(const struct dc *dc)
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)
+/* Returns false when there is nothing to send. */
+bool dcn401_fams2_build_update_config(struct dc *dc, struct dc_state *context, bool enable,
+ struct dc_dmub_fams2_config_data *data)
{
- bool fams2_info_required;
- bool fams2_enabled;
- bool fams2_legacy_no_fams2;
+ memset(data, 0, sizeof(*data));
if (!dc->ctx || !dc->ctx->dmub_srv || !dc->debug.fams2_config.bits.enable)
- return;
+ return false;
+
+ data->fams_version_major = dc->debug.fams_version.major;
+ data->features = dc->debug.fams2_config;
+ data->imm_restore_drr = dc->debug.fams2_imm_restore_drr;
+ data->visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2;
+
+ if (context) {
+ const struct dmub_cmd_fams2_global_config *global =
+ &context->bw_ctx.bw.dcn.fams2_global_config;
+ bool fams2_info_required = global->features.bits.enable != 0u ||
+ global->features.bits.legacy_method_no_fams2 != 0u;
- fams2_enabled = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable != 0u;
- fams2_legacy_no_fams2 = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.legacy_method_no_fams2 != 0u;
- fams2_info_required = fams2_enabled || fams2_legacy_no_fams2;
+ data->global = *global;
+ data->stream_base = context->bw_ctx.bw.dcn.fams2_stream_base_params;
+ data->stream_sub = context->bw_ctx.bw.dcn.fams2_stream_sub_params;
+ data->stream_sub_v2 = context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2;
+ data->enable = enable && fams2_info_required;
+ }
- dc_dmub_srv_fams2_update_config(dc, context, enable && fams2_info_required);
+ return true;
}
static void update_dsc_for_odm_change(struct dc *dc, struct dc_state *context,
@@ -1915,9 +1935,11 @@ void dcn401_unblank_stream(struct pipe_ctx *pipe_ctx,
void dcn401_hardware_release(struct dc *dc)
{
+ struct dc_dmub_fams2_config_data fams2_data;
+
if (!dc->debug.disable_force_pstate_allow_on_hw_release) {
- if (dc->ctx->dmub_srv && dc->debug.fams2_config.bits.enable)
- dc_dmub_srv_fams2_update_config(dc, dc->current_state, false);
+ if (dcn401_fams2_build_update_config(dc, dc->current_state, false, &fams2_data))
+ dc_dmub_srv_fams2_update_config(dc->ctx->dmub_srv, &fams2_data);
/* If pstate unsupported, or still supported
* by firmware, force it supported by dcn
@@ -1938,8 +1960,8 @@ void dcn401_hardware_release(struct dc *dc)
dc->clk_mgr->funcs->update_clocks(dc->clk_mgr, dc->current_state, true);
}
- if (dc->ctx->dmub_srv && dc->debug.fams2_config.bits.enable)
- dc_dmub_srv_fams2_update_config(dc, dc->current_state, false);
+ if (dcn401_fams2_build_update_config(dc, dc->current_state, false, &fams2_data))
+ dc_dmub_srv_fams2_update_config(dc->ctx->dmub_srv, &fams2_data);
}
}
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 d5853cd01a93..fef0dd59a81f 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
@@ -13,6 +13,7 @@
#include "dcn401/dcn401_dccg.h"
struct dc;
+struct dc_dmub_fams2_config_data;
enum ips_ono_state {
ONO_ON = 0,
@@ -89,7 +90,8 @@ void dcn401_optimize_bandwidth_sequence(struct dc *dc,
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);
+bool dcn401_fams2_build_update_config(struct dc *dc, struct dc_state *context, bool enable,
+ struct dc_dmub_fams2_config_data *data);
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);
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 dbeda44ebc8e..1e79b4945801 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
@@ -110,7 +110,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
.wait_for_dcc_meta_propagation = dcn401_wait_for_dcc_meta_propagation,
.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,
+ .fams2_build_update_config = dcn401_fams2_build_update_config,
.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,
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 6711283afcd7..00fcb2559247 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
@@ -110,7 +110,7 @@ static const struct hw_sequencer_funcs dcn42_funcs = {
.wait_for_dcc_meta_propagation = dcn401_wait_for_dcc_meta_propagation,
.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,
+ .fams2_build_update_config = dcn401_fams2_build_update_config,
.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,
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 80125c3596ce..9fde7d1be3e5 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
@@ -112,7 +112,7 @@ static const struct hw_sequencer_funcs dcn60_funcs = {
.wait_for_dcc_meta_propagation = dcn401_wait_for_dcc_meta_propagation,
.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,
+ .fams2_build_update_config = dcn401_fams2_build_update_config,
.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,
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 e8ffae05add8..6580d13d9041 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -36,6 +36,7 @@
#include "dsc/dsc.h"
#include "link_service_types.h"
#include "dmub/inc/dmub_cmd.h"
+#include "dc_dmub_srv.h"
struct pipe_ctx;
struct dc_state;
@@ -359,6 +360,11 @@ struct dmub_hw_control_lock_fast_params {
union dmub_inbox0_cmd_lock_hw command;
};
+struct dmub_fams2_update_config_params {
+ struct dc_dmub_srv *dmub_srv;
+ struct dc_dmub_fams2_config_data data;
+};
+
struct program_surface_config_params {
struct hubp *hubp;
enum surface_pixel_format format;
@@ -1214,6 +1220,7 @@ union block_sequence_params {
struct subvp_save_surf_addr subvp_save_surf_addr;
struct wait_for_dcc_meta_propagation_params wait_for_dcc_meta_propagation_params;
struct dmub_hw_control_lock_fast_params dmub_hw_control_lock_fast_params;
+ struct dmub_fams2_update_config_params dmub_fams2_update_config_params;
struct program_surface_config_params program_surface_config_params;
struct program_mcache_id_and_split_coordinate program_mcache_id_and_split_coordinate;
struct control_cm_hist_params control_cm_hist_params;
@@ -1596,6 +1603,7 @@ enum block_sequence_func {
HUBBUB_INIT_CRB,
HUBBUB_SET_REQUEST_LIMIT,
BIOS_IS_ACCELERATED_MODE,
+ DMUB_FAMS2_UPDATE_CONFIG,
/* This must be the last value in this enum, add new ones above */
HWSS_BLOCK_SEQUENCE_FUNC_COUNT
};
@@ -1907,9 +1915,10 @@ struct hw_sequencer_funcs {
bool (*dmub_hw_control_lock)(struct dc *dc,
struct dc_state *context,
bool lock);
- void (*fams2_update_config)(struct dc *dc,
+ bool (*fams2_build_update_config)(struct dc *dc,
struct dc_state *context,
- bool enable);
+ bool enable,
+ struct dc_dmub_fams2_config_data *data);
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,
@@ -3025,4 +3034,8 @@ 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);
+void hwss_dmub_fams2_update_config(union block_sequence_params *params);
+void hwss_add_dmub_fams2_update_config(struct block_sequence_state *seq_state,
+ struct dc *dc, struct dc_state *context, bool enable);
+
#endif /* __DC_HW_SEQUENCER_H__ */
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 16/28] drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.4
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (14 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 15/28] drm/amd/display: Decouple FAMS2 config update from dc/dc_state and add BLS opcode Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 17/28] drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.2 Alex Hung
` (12 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Dmitry Artemenko,
Mario Limonciello, Alex Deucher, stable
From: Dmitry Artemenko <dmitry.artemenko@amd.com>
[WHY]
amd_hotplug@basic emits a kernel WARN + Call Trace in
optc1_configure_crc / set_reg_field_values on DCN3.1.x.
[HOW]
Add the OTG_CRC1 data and window registers to the DCN3.1.4 OPTC
lists. The hardware supports CRC engine 1 but the mask list only
enrolled CRC0, so the CRC1 field masks resolved to 0 and tripped
the WARN. Tested on DCN 3.1.4: WARN count goes from 2 to 0.
Cc: Roman Li <roman.li@amd.com>
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org # 6.14+
Signed-off-by: Dmitry Artemenko <dmitry.artemenko@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../amd/display/dc/optc/dcn314/dcn314_optc.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h
index 7b43c3ecd46b..25dedcfa8d48 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h
@@ -84,6 +84,12 @@
SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\
SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\
SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\
+ SRI(OTG_CRC1_DATA_RG, OTG, inst),\
+ SRI(OTG_CRC1_DATA_B, OTG, inst),\
+ SRI(OTG_CRC1_WINDOWA_X_CONTROL, OTG, inst),\
+ SRI(OTG_CRC1_WINDOWA_Y_CONTROL, OTG, inst),\
+ SRI(OTG_CRC1_WINDOWB_X_CONTROL, OTG, inst),\
+ SRI(OTG_CRC1_WINDOWB_Y_CONTROL, OTG, inst),\
SR(GSL_SOURCE_SELECT),\
SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\
SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\
@@ -217,6 +223,18 @@
SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\
SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\
SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC_CNTL, OTG_CRC1_SELECT, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_RG, CRC1_R_CR, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_RG, CRC1_G_Y, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_B, CRC1_B_CB, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_END, mask_sh),\
SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\
SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\
SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 17/28] drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.2
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (15 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 16/28] drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.4 Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 18/28] drm/amd/display: Skip dsc sequence for stream if dpms off Alex Hung
` (11 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Dmitry Artemenko,
Mario Limonciello, Alex Deucher, stable
From: Dmitry Artemenko <dmitry.artemenko@amd.com>
[WHY]
amd_hotplug@basic emits a kernel WARN + Call Trace in
optc1_configure_crc / set_reg_field_values on DCN3.1.x.
[HOW]
Add the OTG_CRC1 data and window registers to the DCN3.1 OPTC
lists, matching the DCN3.1.4 fix. DCN3.1.2 hardware supports CRC
engine 1 but the mask list only enrolled CRC0.
Cc: Roman Li <roman.li@amd.com>
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org # 6.14+
Signed-off-by: Dmitry Artemenko <dmitry.artemenko@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../drm/amd/display/dc/optc/dcn31/dcn31_optc.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h
index 19d90c65a22b..a60a96075d3b 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h
@@ -83,6 +83,12 @@
SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\
SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\
SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\
+ SRI(OTG_CRC1_DATA_RG, OTG, inst),\
+ SRI(OTG_CRC1_DATA_B, OTG, inst),\
+ SRI(OTG_CRC1_WINDOWA_X_CONTROL, OTG, inst),\
+ SRI(OTG_CRC1_WINDOWA_Y_CONTROL, OTG, inst),\
+ SRI(OTG_CRC1_WINDOWB_X_CONTROL, OTG, inst),\
+ SRI(OTG_CRC1_WINDOWB_Y_CONTROL, OTG, inst),\
SR(GSL_SOURCE_SELECT),\
SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\
SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\
@@ -217,6 +223,18 @@
SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\
SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\
SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC_CNTL, OTG_CRC1_SELECT, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_RG, CRC1_R_CR, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_RG, CRC1_G_Y, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_B, CRC1_B_CB, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_END, mask_sh),\
SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\
SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\
SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 18/28] drm/amd/display: Skip dsc sequence for stream if dpms off
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (16 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 17/28] drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.2 Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 19/28] drm/amd/display: Add debugfs override for HDMI VRR Alex Hung
` (10 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, George Shen, Wenjing Liu
From: George Shen <george.shen@amd.com>
[WHY]
For previous ASICs, the DSC update sequence was skipped if DSC was not
already previously enabled for the OTG instance (done by checking the
DSCRM_DSC_FORWARD_EN bit in HW). This was done because DSC does not get
reset if the DSC enabled stream was not powered on (DPMS on), resulting
in stale DSC-enabled register state.
This logic is missing from the initial porting of the hw sequencer logic
into the new block sequence building style.
[HOW]
The legacy method of reading the DSCRM HW register requires a hwss
operation, which becomes cumbersome when trying to skip subsequent DSC
programming operations. Instead, check the stream DPMS state in SW and
skip adding the DSC programming operations to the sequence if DPMS is
off.
Cc: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: George Shen <george.shen@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 8 ++++++++
1 file changed, 8 insertions(+)
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 88262cf86598..694c425e22b4 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
@@ -6269,6 +6269,14 @@ bool hwss_add_dsc_sequence_for_stream(struct block_sequence_state *seq_state,
dsc = top_pipe->stream_res.dsc;
stream = top_pipe->stream;
+ /* In some timing-sensitive sequences, the stream may be reset before
+ * powered on (DPMS on). This will cause DSC disablement to be skipped.
+ * Thus, we should skip the DSC sequence if the stream is powered off.
+ * DSC should be programmed at some later point when the stream is powered on.
+ */
+ if (stream->dpms_off)
+ return false;
+
if (stream->ctx && stream->ctx->dc && stream->ctx->dc->res_pool)
dccg = stream->ctx->dc->res_pool->dccg;
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 19/28] drm/amd/display: Add debugfs override for HDMI VRR
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (17 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 18/28] drm/amd/display: Skip dsc sequence for stream if dpms off Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 20/28] drm/amd/display: Enable immediate restore for FAMS on DCN6 Alex Hung
` (9 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen
From: Fangzhi Zuo <jerry.zuo@amd.com>
[WHY]
Provide a debugfs control to force HDMI VRR or disable VRR while debugging
sink capability and display behavior.
[HOW]
Add per-connector VRR override modes for automatic operation, forced
HDMI_VRR, and disabled VRR. Expose the override through debugfs and apply
it while updating HDMI VRR capability state, ranges, and connector
properties.
Cc: IVAN LIPSKI <ivan.lipski@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 ++
.../display/amdgpu_dm/amdgpu_dm_connector.c | 105 ++++++++++++++----
.../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 30 +++++
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 2 +-
4 files changed, 123 insertions(+), 21 deletions(-)
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 656aa0e465eb..43a5cff3332c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -825,6 +825,12 @@ struct amdgpu_hdmi_vsdb_info {
bool replay_mode;
};
+enum amdgpu_dm_vrr_override {
+ AMDGPU_DM_VRR_OVERRIDE_AUTO,
+ AMDGPU_DM_VRR_OVERRIDE_FORCE_HDMI_VRR,
+ AMDGPU_DM_VRR_OVERRIDE_DISABLE_VRR,
+};
+
struct amdgpu_dm_connector {
struct drm_connector base;
@@ -915,6 +921,7 @@ struct amdgpu_dm_connector {
/* Adaptive Sync */
bool pack_sdp_v1_3;
enum adaptive_sync_type as_type;
+ enum amdgpu_dm_vrr_override vrr_override;
struct amdgpu_hdmi_vsdb_info vsdb_info;
/* HDMI HPD debounce support */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index 37b41c887ede..d30aa21cd3ff 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -3210,6 +3210,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
aconnector->audio_inst = -1;
aconnector->pack_sdp_v1_3 = false;
aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE;
+ aconnector->vrr_override = AMDGPU_DM_VRR_OVERRIDE_AUTO;
memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info));
mutex_init(&aconnector->hpd_lock);
mutex_init(&aconnector->handle_mst_msg_ready);
@@ -3834,6 +3835,58 @@ static __maybe_unused int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconne
return valid_vsdb_found ? i : -ENODEV;
}
+static bool amdgpu_dm_apply_hdmi_vrr_override(struct drm_connector *connector,
+ struct dc_sink *sink,
+ bool *force_hdmi_vrr)
+{
+ struct amdgpu_dm_connector *aconnector =
+ to_amdgpu_dm_connector(connector);
+ struct amdgpu_device *adev = drm_to_adev(connector->dev);
+
+ if (aconnector->vrr_override ==
+ AMDGPU_DM_VRR_OVERRIDE_DISABLE_VRR) {
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: FreeSync/VRR disabled by debugfs override on %s\n",
+ connector->name);
+ aconnector->min_vfreq = 0;
+ aconnector->max_vfreq = 0;
+ connector->display_info.monitor_range.min_vfreq = 0;
+ connector->display_info.monitor_range.max_vfreq = 0;
+ connector->display_info.hdmi.vrr_cap.supported = false;
+ connector->display_info.hdmi.vrr_cap.vrr_min = 0;
+ connector->display_info.hdmi.vrr_cap.vrr_max = 0;
+ aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE;
+ aconnector->pack_sdp_v1_3 = false;
+ memset(&aconnector->vsdb_info, 0,
+ sizeof(aconnector->vsdb_info));
+ sink->edid_caps.freesync_vcp_code = 0;
+
+ return true;
+ }
+
+ *force_hdmi_vrr = aconnector->vrr_override ==
+ AMDGPU_DM_VRR_OVERRIDE_FORCE_HDMI_VRR;
+ if (*force_hdmi_vrr && connector->display_info.hdmi.vrr_cap.supported) {
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: HDMI_VRR forced by debugfs override on %s\n",
+ connector->name);
+ aconnector->min_vfreq = 0;
+ aconnector->max_vfreq = 0;
+ aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE;
+ aconnector->pack_sdp_v1_3 = false;
+ memset(&aconnector->vsdb_info, 0,
+ sizeof(aconnector->vsdb_info));
+ sink->edid_caps.freesync_vcp_code = 0;
+ } else if (*force_hdmi_vrr) {
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: HDMI_VRR force override ignored on %s (unsupported)\n",
+ connector->name);
+ *force_hdmi_vrr = false;
+ }
+
+ return false;
+}
+
/**
* amdgpu_dm_update_freesync_caps - Update Freesync capabilities
*
@@ -3860,6 +3913,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
struct amdgpu_device *adev = drm_to_adev(connector->dev);
struct amdgpu_hdmi_vsdb_info vsdb_info = {0};
const struct edid *edid;
+ bool force_hdmi_vrr = false;
bool freesync_capable = false;
enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE;
@@ -3927,27 +3981,38 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
} else if (drm_edid &&
(sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)) {
- has_vsdb = get_amd_vsdb(amdgpu_dm_connector, &vsdb_info);
- amdgpu_dm_connector->vsdb_info = vsdb_info;
- if (has_vsdb) {
- sink->edid_caps.freesync_vcp_code = vsdb_info.freesync_mccs_vcp_code;
-
- if (vsdb_info.freesync_supported) {
- amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz;
- amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz;
- if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
- freesync_capable = true;
+ if (amdgpu_dm_apply_hdmi_vrr_override(connector, sink, &force_hdmi_vrr))
+ goto update;
- connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz;
- connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
+ if (!force_hdmi_vrr) {
+ has_vsdb = get_amd_vsdb(amdgpu_dm_connector, &vsdb_info);
+ amdgpu_dm_connector->vsdb_info = vsdb_info;
+ if (has_vsdb) {
+ sink->edid_caps.freesync_vcp_code =
+ vsdb_info.freesync_mccs_vcp_code;
+
+ if (vsdb_info.freesync_supported) {
+ amdgpu_dm_connector->min_vfreq =
+ vsdb_info.min_refresh_rate_hz;
+ amdgpu_dm_connector->max_vfreq =
+ vsdb_info.max_refresh_rate_hz;
+ if (amdgpu_dm_connector->max_vfreq -
+ amdgpu_dm_connector->min_vfreq > 10)
+ freesync_capable = true;
+
+ connector->display_info.monitor_range.min_vfreq =
+ vsdb_info.min_refresh_rate_hz;
+ connector->display_info.monitor_range.max_vfreq =
+ vsdb_info.max_refresh_rate_hz;
+ }
}
- }
- drm_dbg_driver(adev_to_drm(adev),
- "VRR: amd_vsdb i=%d fs_sup=%d min=%d max=%d fs_capable=%d\n",
- has_vsdb, vsdb_info.freesync_supported,
- vsdb_info.min_refresh_rate_hz,
- vsdb_info.max_refresh_rate_hz, freesync_capable);
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: FreeSync hdmi_freesync=%d min=%d max=%d freesync_capable=%d\n",
+ vsdb_info.freesync_supported,
+ vsdb_info.min_refresh_rate_hz,
+ vsdb_info.max_refresh_rate_hz, freesync_capable);
+ }
/*
* If AMD VSDB didn't provide a valid FreeSync range, fall back to
@@ -3958,7 +4023,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
&connector->display_info.hdmi.vrr_cap;
drm_dbg_driver(adev_to_drm(adev),
- "VRR: HF-VSDB fallback: hdmi_vrr=1 vrr_cap[sup=%d min=%d max=%d] mrange_max=%d\n",
+ "VRR: HDMI_VRR hdmi_vrr=1 vrr_cap[sup=%d min=%d max=%d] mrange_max=%d\n",
vrr_cap->supported, vrr_cap->vrr_min, vrr_cap->vrr_max,
connector->display_info.monitor_range.max_vfreq);
@@ -4049,7 +4114,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
dm_con_state->freesync_capable = freesync_capable;
drm_dbg_driver(adev_to_drm(adev),
- "VRR: caps result: freesync_capable=%d min_vfreq=%d max_vfreq=%d\n",
+ "VRR: caps result: vrr_capable=%d min_vfreq=%d max_vfreq=%d\n",
freesync_capable, amdgpu_dm_connector->min_vfreq,
amdgpu_dm_connector->max_vfreq);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 0cef66e20a86..b6ecd9f051db 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -3114,6 +3114,35 @@ static const struct file_operations dp_mst_link_settings_debugfs_fops = {
.llseek = default_llseek
};
+/* 0: EDID behavior, 1: force HDMI VRR, 2: disable VRR. */
+static int vrr_override_set(void *data, u64 val)
+{
+ struct amdgpu_dm_connector *connector = data;
+
+ if (val > AMDGPU_DM_VRR_OVERRIDE_DISABLE_VRR)
+ return -EINVAL;
+
+ if (connector->vrr_override == val)
+ return 0;
+
+ connector->vrr_override = val;
+ drm_kms_helper_connector_hotplug_event(&connector->base);
+
+ return 0;
+}
+
+static int vrr_override_get(void *data, u64 *val)
+{
+ struct amdgpu_dm_connector *connector = data;
+
+ *val = connector->vrr_override;
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(vrr_override_fops, vrr_override_get,
+ vrr_override_set, "%llu\n");
+
static const struct {
char *name;
const struct file_operations *fops;
@@ -3145,6 +3174,7 @@ static const struct {
char *name;
const struct file_operations *fops;
} hdmi_debugfs_entries[] = {
+ {"vrr_override", &vrr_override_fops},
{"hdcp_sink_capability", &hdcp_sink_capability_fops},
{"hdmi_cec_state", &hdmi_cec_state_fops}
};
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 386ba88c57c6..fa628b2cd3e4 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
@@ -195,7 +195,7 @@ void amdgpu_dm_get_freesync_config_for_crtc(
new_crtc_state->freesync_config = config;
drm_dbg_driver(new_con_state->base.connector->dev,
- "VRR: cfg vrr_enabled=%d vrr_supported=%d fs_capable=%d vrefresh=%d min=%d max=%d state=%d\n",
+ "VRR: cfg vrr_enabled=%d vrr_supported=%d vrr_capable=%d vrefresh=%d min=%d max=%d state=%d\n",
new_crtc_state->base.vrr_enabled,
new_crtc_state->vrr_supported,
new_con_state->freesync_capable, vrefresh,
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 20/28] drm/amd/display: Enable immediate restore for FAMS on DCN6
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (18 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 19/28] drm/amd/display: Add debugfs override for HDMI VRR Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 21/28] drm/amd/display: Expand DSCCLK support check Alex Hung
` (8 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, 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>
[WHAT]
Enable immediate restore for FAMS on DCN6
Cc: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.c
index 50b7779a6ce7..b46b396f45d4 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.c
@@ -721,6 +721,7 @@ static void dcn6_populate_fams2_programming(const struct dml2_core_internal_disp
break;
}
}
+ base_programming->config.bits.imm_restore_drr = true; // enable immediate restore unconditionally for DCN6
switch (pstate_method) {
case dml2_pstate_method_vactive:
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 21/28] drm/amd/display: Expand DSCCLK support check
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (19 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 20/28] drm/amd/display: Enable immediate restore for FAMS on DCN6 Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 22/28] drm/amd/display: Add more backlight Kunit tests Alex Hung
` (7 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Ilya Bakoulin, Dillon Varone
From: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
[WHY & HOW]
Need to add a check for the case where there is 1 DSC slice per ODM
pipe, and DSCCLK exceeds 1/5th of DPREFCLK. Such configurations should
be marked as unsupported.
Cc: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../dml2_core_dcn5_funcs_mode_support.c | 24 ++++++++++++++++---
.../dml2_core_dcn6_funcs_mode_support.c | 19 ++++++++++++++-
.../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c | 1 +
.../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c | 1 +
.../src/inc/dml2_internal_shared_types.h | 1 +
5 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_support.c
index 09519f0f2251..b9aef66d722d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_support.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_support.c
@@ -1151,14 +1151,32 @@ static void dcn5_ms_calculate_dscclk_required(
}
static bool dcn5_ms_check_dscclk_support(
- struct dml2_core_internal_display_mode_lib *mode_lib)
+ struct dml2_core_internal_display_mode_lib *mode_lib, const struct dml2_utm_soc_bb *utm_soc_bb)
{
unsigned int k;
bool support = true;
- for (k = 0; k < mode_lib->ms.num_active_planes; k++)
+ for (k = 0; k < mode_lib->ms.num_active_planes; k++) {
if (mode_lib->ms.required_dscclk_freq_mhz[k] > mode_lib->ms.max_dscclk_freq_mhz)
support = false;
+
+ unsigned int num_dsc_units;
+
+ if (mode_lib->ms.ODMMode[k] == dml2_odm_mode_combine_4to1)
+ num_dsc_units = 4;
+ else if (mode_lib->ms.ODMMode[k] == dml2_odm_mode_combine_3to1)
+ num_dsc_units = 3;
+ else if (mode_lib->ms.ODMMode[k] == dml2_odm_mode_combine_2to1)
+ num_dsc_units = 2;
+ else
+ num_dsc_units = 1;
+
+ if (mode_lib->ms.required_dscclk_freq_mhz[k] > ((double)utm_soc_bb->dprefclk_mhz / 5.0) &&
+ (mode_lib->ms.support.NumberOfDSCSlices[k] / num_dsc_units) == 1) {
+ support = false;
+ }
+ }
+
return support;
}
@@ -2844,7 +2862,7 @@ static bool dcn5_mode_support(struct dml2_core_calcs_mode_support_ex *in_out_par
dcn5_ms_calculate_dscclk_required(display_cfg, mode_lib);
- mode_lib->ms.support.DSCCLKRequiredMoreThanSupported = !dcn5_ms_check_dscclk_support(mode_lib);
+ mode_lib->ms.support.DSCCLKRequiredMoreThanSupported = !dcn5_ms_check_dscclk_support(mode_lib, utm_soc_bb);
dcn5_ms_check_dsc_engine_supports(display_cfg, mode_lib);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_support.c
index 50ca620a4c41..2ca3a603615e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_support.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_support.c
@@ -1516,7 +1516,7 @@ bool dcn6_ms_check_dscclk_support(
const struct dml2_utm_soc_bb *soc_bb = ctx->soc_bb;
DML_LOG_FUNC_ENTER();
- for (k = 0; k < display_cfg->num_planes; k++)
+ for (k = 0; k < display_cfg->num_planes; k++) {
if (inputs->required_dscclk_freq_mhz[k] > (double) soc_bb->max_dscclk_khz / 1000) {
outputs->support.DSCCLKRequiredMoreThanSupported = true;
DML_LOG_VERBOSE("DML::%s: k=%u, DSCCLKRequiredMoreThanSupported = %u\n",
@@ -1524,6 +1524,23 @@ bool dcn6_ms_check_dscclk_support(
break;
}
+ unsigned int num_dsc_units;
+
+ if (inputs->ODMMode[k] == dml2_odm_mode_combine_4to1)
+ num_dsc_units = 4;
+ else if (inputs->ODMMode[k] == dml2_odm_mode_combine_3to1)
+ num_dsc_units = 3;
+ else if (inputs->ODMMode[k] == dml2_odm_mode_combine_2to1)
+ num_dsc_units = 2;
+ else
+ num_dsc_units = 1;
+
+ if (inputs->required_dscclk_freq_mhz[k] > ((double)soc_bb->dprefclk_mhz / 5.0) &&
+ (inputs->support.NumberOfDSCSlices[k] / num_dsc_units) == 1) {
+ outputs->support.DSCCLKRequiredMoreThanSupported = true;
+ }
+ }
+
DML_LOG_DEBUG_BOOL(outputs->support.DSCCLKRequiredMoreThanSupported);
DML_LOG_FUNC_EXIT();
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c
index a58c3944addb..bb45d9b61554 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c
@@ -121,6 +121,7 @@ bool dml2_utm_soc_bb_dcn5_create(struct dml2_utm_soc_bb *utm_soc_bb,
utm_soc_bb->writeback_base_latency_us = soc_bb->qos_parameters.writeback.base_latency_us;
utm_soc_bb->vmin_limit = soc_bb->vmin_limit;
utm_soc_bb->dchub_refclk_mhz = soc_bb->dchub_refclk_mhz;
+ utm_soc_bb->dprefclk_mhz = soc_bb->dprefclk_mhz;
utm_soc_bb->max_outstanding_reqs = soc_bb->max_outstanding_reqs;
utm_soc_bb->return_bus_width_bytes = soc_bb->return_bus_width_bytes;
utm_soc_bb->phy_downspread_percent = soc_bb->phy_downspread_percent;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c
index 9fce6b472aa6..586618d7dd58 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c
@@ -315,6 +315,7 @@ static void dcn6_initialize_from_soc_bb(struct dml2_utm_soc_bb *utm_soc_bb,
utm_soc_bb->writeback_base_latency_us = soc_bb->qos_parameters.writeback.base_latency_us;
utm_soc_bb->vmin_limit = soc_bb->vmin_limit;
utm_soc_bb->dchub_refclk_mhz = soc_bb->dchub_refclk_mhz;
+ utm_soc_bb->dprefclk_mhz = soc_bb->dprefclk_mhz;
utm_soc_bb->max_outstanding_reqs = soc_bb->max_outstanding_reqs;
utm_soc_bb->return_bus_width_bytes = soc_bb->return_bus_width_bytes;
utm_soc_bb->phy_downspread_percent = soc_bb->phy_downspread_percent;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
index fab9d149b3de..f06affe1fbbb 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
@@ -122,6 +122,7 @@ struct dml2_utm_soc_bb {
double hostvm_inefficiency_fraction;
unsigned int max_lsdma_bandwidth_kbps;
unsigned int dchub_refclk_mhz;
+ unsigned int dprefclk_mhz;
unsigned int max_outstanding_reqs;
unsigned long return_bus_width_bytes;
double phy_downspread_percent;
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 22/28] drm/amd/display: Add more backlight Kunit tests
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (20 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 21/28] drm/amd/display: Expand DSCCLK support check Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 23/28] drm/amd/display: Add more color KUnit tests Alex Hung
` (6 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha
[WHAT]
Add KUnit tests for amdgpu_dm_backlight.c:
- amdgpu_dm_backlight_set_level(): the PWM custom luminance curve
(below, between and above the data points, and a zero-width last
segment) and the DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE bypass.
- amdgpu_dm_register_backlight_device(): the non-linear backlight
scale and a hardware readback that differs from the initial
brightness.
- amdgpu_dm_update_connector_ext_caps(): VESA AUX backlight control
when the panel reports DPCD panel luminance control.
[HOW]
Extend the existing PWM set_level test with a table of data point
counts and brightness values, then repeat the call with the debug
mask set. Add a register test with one curve data point that reuses
the mid backlight level fake. Re-run the OLED ext_caps test with
panel_luminance_control set.
Cc: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../tests/amdgpu_dm_backlight_test.c | 79 ++++++++++++++++++-
1 file changed, 78 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
index c6d15fb8ad98..a60c0fbf519d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
@@ -197,12 +197,25 @@ static void dm_test_backlight_set_level_aux_programs_power_module(struct kunit *
*
* With aux_support cleared, set_level() takes the millipercent branch:
* get_brightness_range() + mod_power_set_backlight_percent(). A NULL
- * power_module keeps the call a safe early-false.
+ * power_module keeps the call a safe early-false. The cases walk each segment of
+ * the custom luminance curve; DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE then bypasses it.
*/
static void dm_test_backlight_set_level_pwm_programs_power_module(struct kunit *test)
{
+ static const struct amdgpu_dm_luminance_data curve[] = {
+ { .input_signal = 50, .luminance = 10 },
+ { .input_signal = 100, .luminance = 40 },
+ { .input_signal = 200, .luminance = 80 },
+ { .input_signal = 255, .luminance = 90 },
+ };
+ /* { data_points, brightness }: no curve, below/between/above points, zero-width end */
+ static const u32 cases[][2] = {
+ { 0, 2000 }, { 3, 0 }, { 3, 38550 }, { 3, 65535 }, { 4, 65535 },
+ };
struct amdgpu_display_manager *dm = dm_kunit_alloc_dm(test);
struct dc_link *link = dm_kunit_alloc_link(test);
+ uint saved_mask = amdgpu_dm_get_dc_debug_mask();
+ int i;
setup_test_dm_ddev(test, dm);
mutex_init(&dm->dc_lock);
@@ -212,10 +225,20 @@ static void dm_test_backlight_set_level_pwm_programs_power_module(struct kunit *
dm->backlight_caps[1].aux_support = false;
dm->backlight_caps[1].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
dm->backlight_caps[1].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
+ memcpy(dm->backlight_caps[1].luminance_data, curve, sizeof(curve));
dm->backlight_link[1] = link;
dm_kunit_add_stream_to_state(test, dm->dc->current_state, 0, link);
+ amdgpu_dm_set_dc_debug_mask(saved_mask & ~DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE);
+ for (i = 0; i < ARRAY_SIZE(cases); i++) {
+ dm->backlight_caps[1].data_points = cases[i][0];
+ amdgpu_dm_backlight_set_level(dm, 1, cases[i][1]);
+ KUNIT_EXPECT_EQ_MSG(test, dm->brightness[1], cases[i][1], "case %d", i);
+ }
+
+ amdgpu_dm_set_dc_debug_mask(saved_mask | DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE);
amdgpu_dm_backlight_set_level(dm, 1, 2000);
+ amdgpu_dm_set_dc_debug_mask(saved_mask);
KUNIT_EXPECT_EQ(test, dm->brightness[1], 2000U);
KUNIT_EXPECT_EQ(test, dm->actual_brightness[1], 0U);
@@ -514,6 +537,54 @@ static void dm_test_register_backlight_device_success(struct kunit *test)
adev->dm.backlight_dev[0]), 0);
}
+/**
+ * dm_test_register_backlight_device_custom_curve_readback - Test curve + readback
+ * @test: The KUnit test context
+ *
+ * Custom curve data points select the non-linear backlight scale, and a
+ * hardware readback that differs from the initial brightness must update both
+ * the requested and the actual brightness.
+ */
+static void dm_test_register_backlight_device_custom_curve_readback(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ uint saved_mask = amdgpu_dm_get_dc_debug_mask();
+ struct amdgpu_dm_connector *aconnector;
+ struct amdgpu_dm_backlight_caps *caps;
+ struct dc_link *link = dm_kunit_alloc_link(test);
+ struct backlight_device *bd;
+ struct drm_minor *primary;
+ int ret;
+
+ amdgpu_dm_set_dc_debug_mask(saved_mask & ~DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE);
+ setup_test_link_service(test, link);
+ link->dc->link_srv->edp_get_backlight_level = dm_test_get_backlight_level_mid;
+ primary = kunit_kzalloc(test, sizeof(*primary), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, primary);
+ adev->ddev.primary = primary;
+ adev->dm.backlight_link[0] = link;
+
+ aconnector = dm_kunit_alloc_connector(test, adev, link);
+ aconnector->bl_idx = 0;
+ aconnector->base.kdev = adev->ddev.dev;
+ caps = &adev->dm.backlight_caps[0];
+ caps->min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
+ caps->max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
+ caps->data_points = 1;
+
+ amdgpu_dm_register_backlight_device(aconnector);
+ amdgpu_dm_set_dc_debug_mask(saved_mask);
+
+ bd = adev->dm.backlight_dev[0];
+ KUNIT_ASSERT_NOT_NULL(test, bd);
+ ret = kunit_add_action_or_reset(test, dm_test_unregister_backlight_device, bd);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ KUNIT_EXPECT_EQ(test, bd->props.scale, BACKLIGHT_SCALE_NON_LINEAR);
+ KUNIT_EXPECT_NE(test, adev->dm.brightness[0], (u32)bd->props.brightness);
+ KUNIT_EXPECT_EQ(test, adev->dm.actual_brightness[0], adev->dm.brightness[0]);
+}
+
static struct drm_connector *setup_panel_power_savings_connector(struct kunit *test,
struct device **device_out,
struct dm_connector_state **state_out)
@@ -1567,6 +1638,11 @@ static void dm_test_update_connector_ext_caps_oled_defaults(struct kunit *test)
KUNIT_EXPECT_EQ(test, fixture.adev->dm.backlight_caps[0].aux_max_input_signal, 512);
KUNIT_EXPECT_EQ(test, fixture.adev->dm.backlight_caps[0].aux_min_input_signal, 1);
+ /* DPCD panel luminance control selects VESA AUX over AMD AUX. */
+ fixture.link->dpcd_caps.panel_luminance_control = true;
+ amdgpu_dm_update_connector_ext_caps(fixture.aconnector);
+ KUNIT_EXPECT_EQ(test, fixture.link->backlight_control_type, BACKLIGHT_CONTROL_VESA_AUX);
+
amdgpu_dm_set_backlight_param(saved_backlight);
}
@@ -1934,6 +2010,7 @@ static struct kunit_case dm_backlight_test_cases[] = {
/* amdgpu_dm_register_backlight_device */
KUNIT_CASE(dm_test_register_backlight_device_negative_index),
KUNIT_CASE(dm_test_register_backlight_device_success),
+ KUNIT_CASE(dm_test_register_backlight_device_custom_curve_readback),
/* panel_power_savings_show / store */
KUNIT_CASE(dm_test_panel_power_savings_show_maps_disable_to_zero),
KUNIT_CASE(dm_test_panel_power_savings_show_reports_level),
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 23/28] drm/amd/display: Add more color KUnit tests
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (21 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 22/28] drm/amd/display: Add more backlight Kunit tests Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 24/28] drm/amd/display: Add more CRC " Alex Hung
` (5 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha
[WHAT]
Add KUnit tests for amdgpu_dm_color.c:
- __set_output_tf(): a user LUT with a non-linear (sRGB) transfer
function, which takes the regamma path.
- amdgpu_dm_update_plane_color_mgmt(): a CRTC degamma LUT without the
legacy sRGB regamma, which maps to a linear plane input TF.
- amdgpu_dm_update_plane_color_mgmt(): a wrongly sized plane degamma
LUT, which is rejected by __set_dm_plane_degamma() and leaves the
degamma block in bypass.
[HOW]
Extend dm_test_set_transfer_funcs_with_luts with an sRGB call to
__set_output_tf(). Re-run the CRTC degamma LUT test with
cm_is_degamma_srgb cleared and expect TRANSFER_FUNCTION_LINEAR. Call
the plane degamma LUT test once with a 128-entry LUT before the valid
one and expect TF_TYPE_BYPASS.
Cc: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../amdgpu_dm/tests/amdgpu_dm_color_test.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c
index c07661ef56c1..7ad8c56cbcf3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_color_test.c
@@ -1493,6 +1493,11 @@ static void dm_test_set_transfer_funcs_with_luts(struct kunit *test)
__set_output_tf(tf, lut, MAX_COLOR_LUT_ENTRIES, false),
0);
+ memset(tf, 0, sizeof(*tf));
+ tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+ tf->tf = TRANSFER_FUNCTION_SRGB;
+ KUNIT_EXPECT_EQ(test, __set_output_tf(tf, lut, MAX_COLOR_LUT_ENTRIES, false), 0);
+
memset(tf, 0, sizeof(*tf));
tf->type = TF_TYPE_DISTRIBUTED_POINTS;
tf->tf = TRANSFER_FUNCTION_LINEAR;
@@ -2266,6 +2271,13 @@ static void dm_test_update_plane_color_mgmt_maps_crtc_degamma_lut(struct kunit *
(int)TF_TYPE_DISTRIBUTED_POINTS);
KUNIT_EXPECT_EQ(test, (int)f.dc_plane_state->in_transfer_func.tf,
(int)TRANSFER_FUNCTION_SRGB);
+
+ /* Without legacy sRGB regamma the CRTC LUT applies on a linear base. */
+ f.crtc_state->cm_is_degamma_srgb = false;
+ ret = amdgpu_dm_update_plane_color_mgmt(f.crtc_state, plane_state, f.dc_plane_state);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_EQ(test, (int)f.dc_plane_state->in_transfer_func.tf,
+ (int)TRANSFER_FUNCTION_LINEAR);
}
/**
@@ -2299,6 +2311,12 @@ static void dm_test_update_plane_color_mgmt_plane_degamma_lut(struct kunit *test
struct drm_color_lut *lut;
int ret;
+ /* A wrongly sized plane LUT is ignored and the DGM stays bypassed. */
+ f.dm_plane_state->degamma_lut = dm_test_make_lut_blob(test, 128);
+ ret = amdgpu_dm_update_plane_color_mgmt(f.crtc_state, plane_state, f.dc_plane_state);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_EQ(test, (int)f.dc_plane_state->in_transfer_func.type, (int)TF_TYPE_BYPASS);
+
f.dm_plane_state->degamma_lut =
dm_test_make_lut_blob(test, MAX_COLOR_LUT_ENTRIES);
lut = f.dm_plane_state->degamma_lut->data;
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 24/28] drm/amd/display: Add more CRC KUnit tests
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (22 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 23/28] drm/amd/display: Add more color KUnit tests Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 25/28] drm/amd/display: Add more connector " Alex Hung
` (4 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha
[WHAT]
Add KUnit tests for amdgpu_dm_crc.c:
- amdgpu_dm_crtc_set_crc_source(): a DPRX source on a non-DP
connector bound to the CRTC, a DPRX source on a DP connector that
fails to take a vblank reference, and switching from the CRTC
source to none.
- amdgpu_dm_crtc_handle_crc_irq(): delivering a CRTC CRC read from DC
to the DRM CRC entry queue.
[HOW]
Bind an amdgpu_dm_connector to the CRTC and request "dprx" first as
HDMI, then as DisplayPort on a device without vblank support. Reuse
the DC CRC fixture with a held vblank reference to turn CRTC CRC off
and check the source, skip count and vblank refcount. Register a real
CRTC with vblank support and CRC entries to check the queued CRC.
Cc: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../amdgpu_dm/tests/amdgpu_dm_crc_test.c | 124 ++++++++++++++++++
1 file changed, 124 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crc_test.c
index 29a513dab9cd..7f6340702502 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crc_test.c
@@ -10,8 +10,10 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_connector.h>
+#include <drm/drm_managed.h>
#include <drm/drm_modeset_lock.h>
#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
#include "dc.h"
#include "core_types.h"
@@ -187,6 +189,11 @@ static void dm_test_crc_connector_cleanup(void *data)
drm_connector_cleanup(data);
}
+static const struct drm_crtc_funcs dm_test_crc_crtc_funcs = {
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
static void dm_test_parse_crc_source_none(struct kunit *test)
{
KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_NONE, dm_parse_crc_source("none"));
@@ -673,6 +680,77 @@ static void dm_test_crtc_set_crc_source_dprx_no_connector(struct kunit *test)
AMDGPU_DM_PIPE_CRC_SOURCE_NONE);
}
+/**
+ * dm_test_crtc_set_crc_source_dprx_connector() - Test DPRX connector checks.
+ * @test: KUnit test context.
+ *
+ * Verifies that a DPRX source is rejected for a non-DP connector bound to the
+ * CRTC, and that a DP connector passes the AUX lookup but still fails when the
+ * device has no vblank support.
+ */
+static void dm_test_crtc_set_crc_source_dprx_connector(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct amdgpu_crtc *acrtc = dm_test_alloc_crc_crtc(test, adev);
+ struct amdgpu_dm_connector *aconn;
+ int ret;
+
+ aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconn);
+ /* Init as DP: drm_connector_cleanup() frees the type id from this type's IDA. */
+ ret = drm_connector_init(&adev->ddev, &aconn->base, &dm_test_crc_connector_funcs,
+ DRM_MODE_CONNECTOR_DisplayPort);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ ret = kunit_add_action_or_reset(test, dm_test_crc_connector_cleanup, &aconn->base);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ drm_atomic_helper_connector_reset(&aconn->base);
+ KUNIT_ASSERT_NOT_NULL(test, aconn->base.state);
+ aconn->base.state->crtc = &acrtc->base;
+ /* Balance the reference the state destroy drops for a set CRTC. */
+ drm_connector_get(&aconn->base);
+
+ aconn->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_set_crc_source(&acrtc->base, "dprx"), -EINVAL);
+
+ aconn->base.connector_type = DRM_MODE_CONNECTOR_DisplayPort;
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_set_crc_source(&acrtc->base, "dprx"), -EINVAL);
+ KUNIT_EXPECT_EQ(test, acrtc->dm_irq_params.crc_src, AMDGPU_DM_PIPE_CRC_SOURCE_NONE);
+}
+
+/**
+ * dm_test_crtc_set_crc_source_crtc_to_none() - Test turning CRTC CRC off.
+ * @test: KUnit test context.
+ *
+ * Verifies that switching from the CRTC source to NONE disables DC CRC capture,
+ * drops the vblank reference held while CRC was on, records the new source and
+ * resets the skip counter.
+ */
+static void dm_test_crtc_set_crc_source_crtc_to_none(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct amdgpu_crtc *acrtc = dm_test_alloc_crc_crtc(test, adev);
+ struct dm_test_crc_dc_fixture *fixture;
+ int ret;
+
+ fixture = dm_test_alloc_crc_dc_fixture(test, adev);
+ fixture->dm_state->crc_skip_count = 2;
+ acrtc->base.state = &fixture->dm_state->base;
+ acrtc->dm_irq_params.crc_src = AMDGPU_DM_PIPE_CRC_SOURCE_CRTC;
+ KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
+ atomic_set(&adev->ddev.vblank[0].refcount, 1);
+ dm_test_crc_dc_ctx = fixture;
+
+ ret = amdgpu_dm_crtc_set_crc_source(&acrtc->base, "none");
+ dm_test_crc_dc_ctx = NULL;
+
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_TRUE(test, fixture->configure_crc_called);
+ KUNIT_EXPECT_FALSE(test, fixture->crc_params.enable);
+ KUNIT_EXPECT_EQ(test, atomic_read(&adev->ddev.vblank[0].refcount), 0);
+ KUNIT_EXPECT_EQ(test, acrtc->dm_irq_params.crc_src, AMDGPU_DM_PIPE_CRC_SOURCE_NONE);
+ KUNIT_EXPECT_EQ(test, fixture->dm_state->crc_skip_count, 0);
+}
+
/**
* dm_test_crtc_handle_crc_irq_early_returns() - Test null/missing state exits.
* @test: KUnit test context.
@@ -799,6 +877,49 @@ static void dm_test_crtc_handle_crc_irq_get_crc_fails(struct kunit *test)
KUNIT_EXPECT_EQ(test, fixture->dm_state->crc_skip_count, 2);
}
+/**
+ * dm_test_crtc_handle_crc_irq_adds_entry() - Test CRC delivery to DRM.
+ * @test: KUnit test context.
+ *
+ * Verifies that a CRTC CRC read from DC after the skip window is queued as a
+ * DRM CRC entry on a registered CRTC.
+ */
+static void dm_test_crtc_handle_crc_irq_adds_entry(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct dm_test_crc_dc_fixture *fixture;
+ struct amdgpu_crtc *acrtc;
+ struct drm_crtc_crc *crc;
+ int ret;
+
+ acrtc = drmm_kzalloc(&adev->ddev, sizeof(*acrtc), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, acrtc);
+ ret = drmm_crtc_init_with_planes(&adev->ddev, &acrtc->base, NULL, NULL,
+ &dm_test_crc_crtc_funcs, NULL);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
+ crc = &acrtc->base.crc;
+ crc->entries = kunit_kcalloc(test, DRM_CRC_ENTRIES_NR, sizeof(*crc->entries), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, crc->entries);
+ crc->values_cnt = 3;
+
+ fixture = dm_test_alloc_crc_dc_fixture(test, adev);
+ fixture->dm_state->crc_skip_count = 2;
+ fixture->get_crc_return = true;
+ fixture->crc_r = 0x111;
+ acrtc->base.state = &fixture->dm_state->base;
+ acrtc->dm_irq_params.crc_src = AMDGPU_DM_PIPE_CRC_SOURCE_CRTC;
+ dm_test_crc_dc_ctx = fixture;
+
+ amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
+ dm_test_crc_dc_ctx = NULL;
+ /* Keep drm_crtc_cleanup() from freeing the KUnit-managed state. */
+ acrtc->base.state = NULL;
+
+ KUNIT_EXPECT_EQ(test, crc->head, 1);
+ KUNIT_EXPECT_EQ(test, crc->entries[0].crcs[0], 0x111U);
+}
+
/**
* dm_test_need_dp_aux() - Test dm_need_dp_aux().
* @test: KUnit test context.
@@ -944,12 +1065,15 @@ static struct kunit_case dm_crc_test_cases[] = {
KUNIT_CASE(dm_test_crtc_set_crc_source_none_no_stream),
KUNIT_CASE(dm_test_crtc_set_crc_source_none_commit),
KUNIT_CASE(dm_test_crtc_set_crc_source_dprx_no_connector),
+ KUNIT_CASE(dm_test_crtc_set_crc_source_dprx_connector),
+ KUNIT_CASE(dm_test_crtc_set_crc_source_crtc_to_none),
/* amdgpu_dm_crtc_handle_crc_irq() */
KUNIT_CASE(dm_test_crtc_handle_crc_irq_early_returns),
KUNIT_CASE(dm_test_crtc_handle_crc_irq_disabled_source),
KUNIT_CASE(dm_test_crtc_handle_crc_irq_skips_initial_frames),
KUNIT_CASE(dm_test_crtc_handle_crc_irq_dprx_after_skip),
KUNIT_CASE(dm_test_crtc_handle_crc_irq_get_crc_fails),
+ KUNIT_CASE(dm_test_crtc_handle_crc_irq_adds_entry),
/* dm_need_dp_aux() */
KUNIT_CASE(dm_test_need_dp_aux),
/* dm_crc_source_should_start_dprx() */
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 25/28] drm/amd/display: Add more connector KUnit tests
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (23 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 24/28] drm/amd/display: Add more CRC " Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 26/28] drm/amd/display: Update alt shared lib to use dynamic state Alex Hung
` (3 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha
[WHAT]
Add KUnit tests for amdgpu_dm_connector.c:
- amdgpu_dm_initialize_hdmi_connector(): CEC setup skipped by
DC_DISABLE_HDMI_CEC.
- amdgpu_dm_hdmi_cec_set_edid() and hdmi_cec_unset_edid(): forwarding
to a registered CEC notifier.
- amdgpu_dm_connector_destroy(): releasing the pending HDMI HPD
debounce sink and an unregistered backlight index.
- dm_encoder_helper_atomic_check(): an MST mode forced to YCbCr 4:2:0.
- amdgpu_dm_create_validate_stream_for_sink(): a YCbCr 4:2:0 capable
mode and a sink-reported bpc that rules out every depth.
- amdgpu_dm_connector_atomic_check(): a connector missing from the
commit.
- amdgpu_dm_connector_add_common_modes(): common modes already probed.
- parse_edid_displayid_vrr(): a 10-bit max refresh rate.
- hdmi_frl_status_polling_work(): skipping an inactive FRL link.
[HOW]
Extend the existing tests for these functions instead of adding new
cases. Add dm_test_set_420_also_mode() to load CEA VIC 16 and mark it
YCbCr 4:2:0 capable, shared by the encoder and stream tests.
Fix a use-after-free in the connector init tests: the i2c adapter
parent was freed by KUnit before devres deleted the adapter. Manage
the parent with devres on adev->dev so the adapter is deleted first.
Cc: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../tests/amdgpu_dm_connector_test.c | 80 ++++++++++++++++---
1 file changed, 70 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
index 7965a221e0e9..0a32f24e9132 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
@@ -29,6 +29,7 @@
#include "amdgpu_dm_connector.h"
#include "amdgpu_dm_backlight.h"
#include "amdgpu_dm_hdcp.h"
+#include "amdgpu_dm_irq.h"
#include "amdgpu_dm_psr.h"
#include "include/grph_object_id.h"
#include "amdgpu_dm_kunit_test_helpers.h"
@@ -5128,6 +5129,11 @@ static void dm_test_destroy_releases_dc_sink(struct kunit *test)
/* Extra reference so the sink survives destroy for inspection. */
dc_sink_retain(sink);
aconnector->dc_sink = sink;
+ dc_sink_retain(sink);
+ aconnector->hdmi_prev_sink = sink;
+ aconnector->hdmi_hpd_debounce_delay_ms = 100;
+ INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, amdgpu_dm_hdmi_hpd_debounce_work);
+ aconnector->bl_idx = 0;
amdgpu_dm_connector_destroy(&aconnector->base);
@@ -5233,6 +5239,18 @@ struct dm_test_atomic_check_ctx {
struct drm_crtc_state *crtc_state;
};
+/* Load CEA VIC 16 (1080p60) into @mode and mark it YCbCr 4:2:0 capable on @conn. */
+static void dm_test_set_420_also_mode(struct kunit *test, struct drm_device *drm,
+ struct drm_connector *conn, struct drm_display_mode *mode)
+{
+ struct drm_display_mode *cea = drm_display_mode_from_cea_vic(drm, 16);
+
+ KUNIT_ASSERT_NOT_NULL(test, cea);
+ drm_mode_copy(mode, cea);
+ drm_mode_destroy(drm, cea);
+ set_bit(16, conn->display_info.hdmi.y420_cmdb_modes);
+}
+
static struct dm_test_atomic_check_ctx *
dm_test_atomic_check_ctx_alloc(struct kunit *test, int connector_type)
{
@@ -5501,6 +5519,9 @@ static void dm_test_atomic_check_mst_finds_vcpi_slots(struct kunit *test)
dm_test_atomic_check_mst_scaffold(test, ctx, &s, true);
s.state->duplicated = false;
ctx->dm_state->base.max_requested_bpc = 8;
+ dm_test_set_420_also_mode(test, ctx->drm, &ctx->aconnector->base,
+ &ctx->crtc_state->adjusted_mode);
+ ctx->aconnector->force_yuv_pixel_format = PIXEL_ENCODING_YCBCR420;
KUNIT_EXPECT_EQ(test,
dm_encoder_helper_atomic_check(&ctx->aenc->base,
@@ -5999,6 +6020,8 @@ static void dm_test_add_common_modes_edp_adds(struct kunit *test)
mutex_lock(&ctx->drm->mode_config.mutex);
amdgpu_dm_connector_add_common_modes(&ctx->aenc->base,
&ctx->aconnector->base);
+ /* A second pass finds every common mode already probed. */
+ amdgpu_dm_connector_add_common_modes(&ctx->aenc->base, &ctx->aconnector->base);
mutex_unlock(&ctx->drm->mode_config.mutex);
KUNIT_EXPECT_EQ(test, ctx->aconnector->num_modes, 10);
@@ -6664,6 +6687,12 @@ static void dm_test_parse_displayid_vrr_sets_range(struct kunit *test)
KUNIT_EXPECT_EQ(test, connector->display_info.monitor_range.min_vfreq, 40);
KUNIT_EXPECT_EQ(test, connector->display_info.monitor_range.max_vfreq, 144);
+
+ /* Flags bit 0 extends max vfreq with two bits from the next byte. */
+ ext[2] = 0x01;
+ ext[12] = 0x01;
+ parse_edid_displayid_vrr(connector, edid);
+ KUNIT_EXPECT_EQ(test, connector->display_info.monitor_range.max_vfreq, 400);
}
/**
@@ -6923,15 +6952,23 @@ static void dm_test_create_validate_stream_no_valid_bpc(struct kunit *test)
ctx->mode,
ctx->dm_state, NULL);
KUNIT_EXPECT_NULL(test, stream);
+
+ /* Same result when the sink-reported bpc is the limiting cap. */
+ ctx->dm_state->base.max_requested_bpc = 16;
+ ctx->aconnector->base.display_info.bpc = 4;
+ stream = amdgpu_dm_create_validate_stream_for_sink(&ctx->aconnector->base, ctx->mode,
+ ctx->dm_state, NULL);
+ KUNIT_EXPECT_NULL(test, stream);
}
/**
* dm_test_create_validate_stream_hdmi_ycbcr - Test the HDMI encoding mask
* @test: The KUnit test context
*
- * A native HDMI sink advertising YCbCr 4:4:4 and 4:2:2 exercises HDMI endpoint
- * detection and the YCbCr444/YCbCr422 mask branches; the low bpc cap still
- * prunes every depth, so the helper returns NULL.
+ * A native HDMI sink advertising YCbCr 4:4:4 and 4:2:2, driving a YCbCr 4:2:0
+ * capable mode, exercises HDMI endpoint detection and the YCbCr444, YCbCr422
+ * and YCbCr420 mask branches; the low bpc cap still prunes every depth, so the
+ * helper returns NULL.
*/
static void dm_test_create_validate_stream_hdmi_ycbcr(struct kunit *test)
{
@@ -6943,6 +6980,7 @@ static void dm_test_create_validate_stream_hdmi_ycbcr(struct kunit *test)
ctx->aconnector->base.display_info.color_formats =
BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
+ dm_test_set_420_also_mode(test, ctx->drm, &ctx->aconnector->base, ctx->mode);
stream = amdgpu_dm_create_validate_stream_for_sink(&ctx->aconnector->base,
ctx->mode,
@@ -7371,6 +7409,11 @@ static void dm_test_conn_atomic_check_no_crtc(struct kunit *test)
ret = amdgpu_dm_connector_atomic_check(&ctx->aconn->base, ctx->state);
KUNIT_EXPECT_EQ(test, ret, 0);
+
+ /* A connector missing from the commit is rejected (WARN only). */
+ ctx->state->connectors[0].old_state = NULL;
+ ret = amdgpu_dm_connector_atomic_check(&ctx->aconn->base, ctx->state);
+ KUNIT_EXPECT_EQ(test, ret, -EINVAL);
}
/**
@@ -8931,6 +8974,12 @@ static void dm_test_frl_skips_zero_rate(struct kunit *test)
dm_test_frl_run(ctx);
KUNIT_EXPECT_EQ(test, dm_test_frl_poll_calls, 0);
+
+ /* An inactive link is skipped as well. */
+ link->frl_link_settings.frl_link_rate = HDMI_FRL_LINK_RATE_3GBPS;
+ link->link_status.link_active = false;
+ dm_test_frl_run(ctx);
+ KUNIT_EXPECT_EQ(test, dm_test_frl_poll_calls, 0);
}
/**
@@ -9320,16 +9369,25 @@ static void dm_test_init_helper_hpd_debounce_disabled(struct kunit *test)
* dm_test_initialize_hdmi_cec_registers - Test the CEC notifier is registered
* @test: The KUnit test context
*
- * Without DC_DISABLE_HDMI_CEC in the debug mask a CEC notifier is created for
- * the connector.
+ * With DC_DISABLE_HDMI_CEC in the debug mask CEC setup is skipped with -EINVAL.
+ * Without it a CEC notifier is created for the connector, and setting and
+ * unsetting the EDID are forwarded to that notifier.
*/
static void dm_test_initialize_hdmi_cec_registers(struct kunit *test)
{
struct dm_test_init_helper_ctx *ctx =
dm_test_init_helper_ctx_alloc(test, DRM_MODE_CONNECTOR_HDMIA);
+ uint saved_mask = amdgpu_dm_get_dc_debug_mask();
+
+ amdgpu_dm_set_dc_debug_mask(saved_mask | DC_DISABLE_HDMI_CEC);
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_initialize_hdmi_connector(ctx->aconnector), -EINVAL);
+ amdgpu_dm_set_dc_debug_mask(saved_mask);
KUNIT_EXPECT_EQ(test, amdgpu_dm_initialize_hdmi_connector(ctx->aconnector), 0);
KUNIT_EXPECT_NOT_NULL(test, ctx->aconnector->notifier);
+
+ amdgpu_dm_hdmi_cec_set_edid(ctx->aconnector);
+ hdmi_cec_unset_edid(ctx->aconnector);
}
/* Tests for amdgpu_dm_update_freesync_caps() */
@@ -9734,11 +9792,13 @@ static void dm_test_fs_caps_disables_replay(struct kunit *test)
/*
* amdgpu_dm_create_i2c() parents the adapter on adev->pdev->dev, so
* devm_i2c_add_adapter() needs a registered device there. Provide one by
- * registering the device embedded in a KUnit allocated pci_dev.
+ * registering the device embedded in a pci_dev managed by adev->dev's devres.
+ * The adapter is devres managed on adev->dev too and is added later, so it is
+ * deleted before its parent is unregistered and freed.
*/
static void dm_test_conn_init_release_dev(struct device *dev)
{
- /* Backing storage is KUnit managed, so there is nothing to free. */
+ /* Backing storage is devres managed, so there is nothing to free. */
}
static void dm_test_conn_init_unregister_dev(void *data)
@@ -9781,7 +9841,7 @@ dm_test_conn_init_ctx_alloc(struct kunit *test, enum signal_type signal)
ctx->adev->mode_info.num_crtc = 1;
dm_test_create_mode_props(test, ctx->adev);
- pdev = kunit_kzalloc(test, sizeof(*pdev), GFP_KERNEL);
+ pdev = devm_kzalloc(dev, sizeof(*pdev), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, pdev);
device_initialize(&pdev->dev);
pdev->dev.parent = dev;
@@ -9789,8 +9849,8 @@ dm_test_conn_init_ctx_alloc(struct kunit *test, enum signal_type signal)
KUNIT_ASSERT_EQ(test, dev_set_name(&pdev->dev, "dm-test-i2c-parent"), 0);
KUNIT_ASSERT_EQ(test, device_add(&pdev->dev), 0);
KUNIT_ASSERT_EQ(test,
- kunit_add_action_or_reset(test, dm_test_conn_init_unregister_dev,
- &pdev->dev), 0);
+ devm_add_action_or_reset(dev, dm_test_conn_init_unregister_dev,
+ &pdev->dev), 0);
ctx->adev->pdev = pdev;
ctx->dm = &ctx->adev->dm;
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 26/28] drm/amd/display: Update alt shared lib to use dynamic state
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (24 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 25/28] drm/amd/display: Add more connector " Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 27/28] drm/amd/display: [FW Promotion] Release 0.1.82.0 Alex Hung
` (2 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, 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>
[WHAT]
Update to use dynamic state pipe_viewports struct instead of from
static state.
Cc: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../src/dml2_standalone_libraries/alternate_pstate_shared_lib.c | 2 +-
.../src/dml2_standalone_libraries/alternate_pstate_shared_lib.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c
index ec2f2bdada6a..127e594561f0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c
@@ -989,7 +989,7 @@ static void populate_lsdma(
static void populate_copy_params(struct calculate_lsdma_copy_params *p, uint8_t svp_idx, uint8_t pipe_idx)
{
struct dmub_fams2_cmd_alternate_stream_static_state *state = p->alternate_static_state;
- struct plane_pipe_rect *pipe_vp = &p->alternate_static_state->pipe_viewports[pipe_idx];
+ struct plane_pipe_rect *pipe_vp = &p->alternate_stream_dynamic_state->pipe_viewports[pipe_idx];
populate_lsdma(state, &pipe_vp->luma, &p->svp[svp_idx], p->plane_index, pipe_idx, false, &p->out[svp_idx]);
if (state->config[p->plane_index].bits.is_multi_planar) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.h
index 8983ea6937a6..1a3b2ff2d369 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.h
@@ -81,6 +81,7 @@ struct calculate_lsdma_copy_params {
/* inputs */
struct dmub_fams2_cmd_stream_static_base_state *base;
struct dmub_fams2_cmd_alternate_stream_static_state *alternate_static_state;
+ struct dmub_fams2_alternate_stream_dynamic_state *alternate_stream_dynamic_state;
uint8_t plane_index;
struct svp_params svp[2]; // array of 2 for svp0 and svp1
struct svp_params svp_c[2]; // array of 2 for svp0 and svp1
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 27/28] drm/amd/display: [FW Promotion] Release 0.1.82.0
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (25 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 26/28] drm/amd/display: Update alt shared lib to use dynamic state Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-27 23:17 ` [PATCH 28/28] drm/amd/display: Promote DC to 3.2.405 Alex Hung
2026-10-30 15:42 ` [PATCH 00/28] DC Patches Oct 27, 2026 Leo Li
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Taimur Hassan
From: Taimur Hassan <Syed.Hassan@amd.com>
Updated DMUB interface
- Add per-plane TMZ ID to FAMS2 alternate stream dynamic state and
drop the TMZ bit from the static state config
- Add IDLE_OPT_SET_Z8_ALLOW command to allow or disallow Z8
Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
.../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 31 ++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index 27723ccec6ac..8684b1398d4e 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -2627,6 +2627,8 @@ struct dmub_fams2_alternate_stream_dynamic_state {
uint8_t cursor_size[3]; // Cursor array per plane for now - if we assume a single cursor, then we don't need an array
uint8_t disabled_pipe_mask; // bitmask of pipes with RECOUT_HEIGHT == 0 (disabled)
struct plane_pipe_rect pipe_viewports[4];
+ uint8_t tmz_id[3]; // TMZ ID per plane
+ uint8_t pad; // to maintain alignment
/* outputs: */
uint16_t subvp_start_line_a[3];
uint16_t subvp_height_a[3];
@@ -2697,7 +2699,6 @@ struct dmub_fams2_cmd_alternate_stream_static_state {
uint8_t vertical_access : 1; // vertical_access = 1 means 90 or 270 rotation
uint8_t access_direction : 1; // access_direction = 1 means bigger to smaller coordinations (e.g., scan from 2160 to 0 as opposed to regular 0 to 2160)
uint8_t dcc : 1;
- uint8_t tmz : 1; // TODO: Need to assign outside of DML (DML not aware of TMZ)
} bits;
uint8_t all;
} config[3];
@@ -2986,6 +2987,11 @@ enum dmub_cmd_idle_opt_type {
* DCN notify to release HW.
*/
DMUB_CMD__IDLE_OPT_RELEASE_HW = 4,
+
+ /**
+ * DCN allow or disallow Z8.
+ */
+ DMUB_CMD__IDLE_OPT_SET_Z8_ALLOW = 5,
};
/**
@@ -3039,6 +3045,25 @@ struct dmub_rb_cmd_idle_opt_set_dc_power_state {
struct dmub_idle_opt_set_dc_power_state_data data;
};
+/**
+ * union dmub_idle_opt_set_z8_allow_data - Data passed to FW in a DMUB_CMD__IDLE_OPT_SET_Z8_ALLOW command.
+ */
+union dmub_idle_opt_set_z8_allow_data {
+ struct {
+ uint32_t allow: 1; /**< 0: disallow Z8, 1: allow Z8 */
+ uint32_t reserved: 31; /**< Reserved for expansion; sender zeroes */
+ } bits; /**< bitfields */
+ uint32_t all; /**< union of all bitfields */
+};
+
+/**
+ * struct dmub_rb_cmd_idle_opt_set_z8_allow - Data passed to FW in a DMUB_CMD__IDLE_OPT_SET_Z8_ALLOW command.
+ */
+struct dmub_rb_cmd_idle_opt_set_z8_allow {
+ struct dmub_cmd_header header; /**< header */
+ union dmub_idle_opt_set_z8_allow_data data; /**< Z8 allow policy */
+};
+
/**
* struct dmub_clocks - Clock update notification.
*/
@@ -8017,6 +8042,10 @@ union dmub_rb_cmd {
* Definition of a DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE command.
*/
struct dmub_rb_cmd_idle_opt_set_dc_power_state idle_opt_set_dc_power_state;
+ /**
+ * Definition of a DMUB_CMD__IDLE_OPT_SET_Z8_ALLOW command.
+ */
+ struct dmub_rb_cmd_idle_opt_set_z8_allow idle_opt_set_z8_allow;
/*
* Definition of a DMUB_CMD__REPLAY_COPY_SETTINGS command.
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 28/28] drm/amd/display: Promote DC to 3.2.405
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (26 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 27/28] drm/amd/display: [FW Promotion] Release 0.1.82.0 Alex Hung
@ 2026-10-27 23:17 ` Alex Hung
2026-10-30 15:42 ` [PATCH 00/28] DC Patches Oct 27, 2026 Leo Li
28 siblings, 0 replies; 30+ messages in thread
From: Alex Hung @ 2026-10-27 23:17 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
Alex Hung, James Lin, Chenyu Chen, Taimur Hassan
From: Taimur Hassan <Syed.Hassan@amd.com>
This version brings along the following updates:
- Decouple FAMS2 config update from dc/dc_state and add a BLS opcode.
- Enable immediate restore for FAMS on DCN6 and indicate wait_resp
based on FAMS in the disable path.
- Configure alternate-channel apertures and update the alt shared lib
to use dynamic state.
- Parameterize the FCLK/PPT/Temp Read P-State optimizer and update
rounding for VM stage groups.
- Remove DCN401 RDPCS PHY state reads.
- Adjust DSC slice calc. policy and expand DSCCLK support check.
- Skip DSC sequence for stream if DPMS is off.
- Reset DET of HUBPs without a plane before outstanding updates.
- Add missing OTG_CRC1 reg/mask entries for DCN3.1.2 and DCN3.1.4.
- Add debugfs override for HDMI VRR and fix unadvertised mode
detection.
- Support replay frame update interval and allow bypassing the
link_off_frame_count check in replay debug mode.
- Avoid closing unowned DDC pins.
- Add visual confirm full viewport debug option.
- Use DCN6 driver_if for PPCLK_e enum.
- Add more backlight, color, CRC and connector KUnit tests.
- Various cleanups.
Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com>
Signed-off-by: Alex Hung <alex.hung@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 fa4c142ac271..2715ffc4fbc2 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -69,7 +69,7 @@ struct dcn_dsc_reg_state;
struct dcn_optc_reg_state;
struct dcn_dccg_reg_state;
-#define DC_VER "3.2.404"
+#define DC_VER "3.2.405"
/**
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
--
2.53.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 00/28] DC Patches Oct 27, 2026
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
` (27 preceding siblings ...)
2026-10-27 23:17 ` [PATCH 28/28] drm/amd/display: Promote DC to 3.2.405 Alex Hung
@ 2026-10-30 15:42 ` Leo Li
28 siblings, 0 replies; 30+ messages in thread
From: Leo Li @ 2026-10-30 15:42 UTC (permalink / raw)
To: Alex Hung, amd-gfx
Cc: Harry Wentland, Aurabindo Pillai, Roman Li, Wayne Lin, Tom Chung,
Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski, James Lin,
Chenyu Chen
On 2026-10-27 19:16, Alex Hung wrote:
> This DC patchset brings improvements in multiple areas. In summary, we have:
>
> * Fixes on mode detection, DSC with DPMS off and HUBP DET reset
> * Fixes on DDC pins and missing OTG_CRC1 regs for DCN3.1.x
> * Improvements on DCN6 FAMS immediate restore and PPCLK_e enum
> * Improvements on DSCCLK check and DSC slice calc policy
> * Improvements on Replay frame update interval and debug mode
> * Improvements on DML VM rounding and P-State optimizer
> * Removal of DCN401 RDPCS PHY state reads
> * New debug options for HDMI VRR and visual confirm
> * More KUnit tests for connector, CRC, color and backlight
>
> Cc: Dan Wheeler <daniel.wheeler@amd.com>
Series is
Reviewed-by: Leo Li <sunpeng.li@amd.com>
Thanks,
Leo
>
> Alex Hung (5):
> drm/amd/display: Avoid closing unowned DDC pins
> drm/amd/display: Add more backlight Kunit tests
> drm/amd/display: Add more color KUnit tests
> drm/amd/display: Add more CRC KUnit tests
> drm/amd/display: Add more connector KUnit tests
>
> Allen Li (1):
> drm/amd/display: Allow bypassing link_off_frame_count check for replay
> debug mode
>
> Alvin Lee (4):
> drm/amd/display: Add visual confirm full viewport debug option
> drm/amd/display: Indicate wait_resp based on FAMS even in disable path
> drm/amd/display: Enable immediate restore for FAMS on DCN6
> drm/amd/display: Update alt shared lib to use dynamic state
>
> Austin Zheng (2):
> drm/amd/display: Update Rounding For VM stage groups
> drm/amd/display: Parameterize FCLK/PPT/Temp Read P-State Optimizer
>
> Dmitry Artemenko (2):
> drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.4
> drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.2
>
> Dominik Kaszewski (1):
> drm/amd/display: Clarify endianness error
>
> Fangzhi Zuo (2):
> drm/amd/display: Fix unadvertised mode detection
> drm/amd/display: Add debugfs override for HDMI VRR
>
> George Shen (1):
> drm/amd/display: Skip dsc sequence for stream if dpms off
>
> Ilya Bakoulin (2):
> drm/amd/display: Adjust DSC slice calc. policy
> drm/amd/display: Expand DSCCLK support check
>
> Ivan Lipski (2):
> drm/amd/display: Use DCN6 driver_if for PPCLK_e enum
> drm/amd/display: Configure alternate-channel apertures
>
> Meenakshikumar Somasundaram (1):
> drm/amd/display: Support replay frame update interval
>
> Rafal Ostrowski (1):
> drm/amd/display: Decouple FAMS2 config update from dc/dc_state and add
> BLS opcode
>
> Roman Li (1):
> drm/amd/display: Reset DET of HUBPs without a plane before outstanding
> updates
>
> Taimur Hassan (2):
> drm/amd/display: [FW Promotion] Release 0.1.82.0
> drm/amd/display: Promote DC to 3.2.405
>
> Tony Cheng (1):
> drm/amd/display: Remove DCN401 RDPCS PHY state reads
>
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 +
> .../display/amdgpu_dm/amdgpu_dm_connector.c | 110 +++++++++++++---
> .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 30 +++++
> .../amd/display/amdgpu_dm/amdgpu_dm_dmub.c | 63 +++++++++
> .../display/amdgpu_dm/amdgpu_dm_freesync.c | 2 +-
> .../tests/amdgpu_dm_backlight_test.c | 79 ++++++++++-
> .../amdgpu_dm/tests/amdgpu_dm_color_test.c | 18 +++
> .../tests/amdgpu_dm_connector_test.c | 118 +++++++++++++++--
> .../amdgpu_dm/tests/amdgpu_dm_crc_test.c | 124 ++++++++++++++++++
> .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c | 37 +++++-
> drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +-
> .../drm/amd/display/dc/core/dc_hw_sequencer.c | 69 ++++++++++
> .../gpu/drm/amd/display/dc/core/dc_resource.c | 47 ++++++-
> drivers/gpu/drm/amd/display/dc/dc.h | 4 +-
> drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 113 ++++++++--------
> drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 27 +++-
> drivers/gpu/drm/amd/display/dc/dc_types.h | 3 +
> .../gpu/drm/amd/display/dc/dce/dmub_replay.c | 1 +
> .../gpu/drm/amd/display/dc/dce/dmub_replay.h | 1 -
> .../dc/dcn10/dcn10_hw_sequencer_debug.c | 16 +--
> .../dc/dio/dcn401/dcn401_dio_link_encoder.c | 22 +---
> .../dc/dio/dcn401/dcn401_dio_link_encoder.h | 8 --
> .../dml2_core/dml2_core_dcn5_calcs_dchub.c | 2 +-
> .../dml2_core_dcn5_funcs_mode_support.c | 24 +++-
> .../dml2_core_dcn6_funcs_mode_programming.c | 1 +
> .../dml2_core_dcn6_funcs_mode_support.c | 19 ++-
> .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c | 25 ++--
> .../alternate_pstate_shared_lib.c | 2 +-
> .../alternate_pstate_shared_lib.h | 1 +
> .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c | 1 +
> .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c | 1 +
> .../src/inc/dml2_internal_shared_types.h | 4 +
> drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 24 +++-
> .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c | 1 +
> drivers/gpu/drm/amd/display/dc/dsc/dsc.h | 1 +
> .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 64 ++++++---
> .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 4 +-
> .../amd/display/dc/hwss/dcn401/dcn401_init.c | 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 | 20 ++-
> .../drm/amd/display/dc/inc/hw/link_encoder.h | 2 -
> .../dc/link/protocols/link_dp_capability.c | 6 +-
> .../amd/display/dc/optc/dcn31/dcn31_optc.h | 18 +++
> .../amd/display/dc/optc/dcn314/dcn314_optc.h | 18 +++
> .../dc/resource/dcn401/dcn401_resource.c | 10 +-
> .../dc/resource/dcn60/dcn60_resource.c | 1 +
> .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 31 ++++-
> .../amd/display/include/link_service_types.h | 2 +-
> 49 files changed, 987 insertions(+), 206 deletions(-)
>
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2026-10-30 15:43 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-27 23:16 [PATCH 00/28] DC Patches Oct 27, 2026 Alex Hung
2026-10-27 23:16 ` [PATCH 01/28] drm/amd/display: Use DCN6 driver_if for PPCLK_e enum Alex Hung
2026-10-27 23:16 ` [PATCH 02/28] drm/amd/display: Allow bypassing link_off_frame_count check for replay debug mode Alex Hung
2026-10-27 23:16 ` [PATCH 03/28] drm/amd/display: Clarify endianness error Alex Hung
2026-10-27 23:17 ` [PATCH 04/28] drm/amd/display: Add visual confirm full viewport debug option Alex Hung
2026-10-27 23:17 ` [PATCH 05/28] drm/amd/display: Remove DCN401 RDPCS PHY state reads Alex Hung
2026-10-27 23:17 ` [PATCH 06/28] drm/amd/display: Adjust DSC slice calc. policy Alex Hung
2026-10-27 23:17 ` [PATCH 07/28] drm/amd/display: Configure alternate-channel apertures Alex Hung
2026-10-27 23:17 ` [PATCH 08/28] drm/amd/display: Avoid closing unowned DDC pins Alex Hung
2026-10-27 23:17 ` [PATCH 09/28] drm/amd/display: Support replay frame update interval Alex Hung
2026-10-27 23:17 ` [PATCH 10/28] drm/amd/display: Indicate wait_resp based on FAMS even in disable path Alex Hung
2026-10-27 23:17 ` [PATCH 11/28] drm/amd/display: Update Rounding For VM stage groups Alex Hung
2026-10-27 23:17 ` [PATCH 12/28] drm/amd/display: Fix unadvertised mode detection Alex Hung
2026-10-27 23:17 ` [PATCH 13/28] drm/amd/display: Parameterize FCLK/PPT/Temp Read P-State Optimizer Alex Hung
2026-10-27 23:17 ` [PATCH 14/28] drm/amd/display: Reset DET of HUBPs without a plane before outstanding updates Alex Hung
2026-10-27 23:17 ` [PATCH 15/28] drm/amd/display: Decouple FAMS2 config update from dc/dc_state and add BLS opcode Alex Hung
2026-10-27 23:17 ` [PATCH 16/28] drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.4 Alex Hung
2026-10-27 23:17 ` [PATCH 17/28] drm/amd/display: Add missing OTG_CRC1 reg/mask entries for DCN3.1.2 Alex Hung
2026-10-27 23:17 ` [PATCH 18/28] drm/amd/display: Skip dsc sequence for stream if dpms off Alex Hung
2026-10-27 23:17 ` [PATCH 19/28] drm/amd/display: Add debugfs override for HDMI VRR Alex Hung
2026-10-27 23:17 ` [PATCH 20/28] drm/amd/display: Enable immediate restore for FAMS on DCN6 Alex Hung
2026-10-27 23:17 ` [PATCH 21/28] drm/amd/display: Expand DSCCLK support check Alex Hung
2026-10-27 23:17 ` [PATCH 22/28] drm/amd/display: Add more backlight Kunit tests Alex Hung
2026-10-27 23:17 ` [PATCH 23/28] drm/amd/display: Add more color KUnit tests Alex Hung
2026-10-27 23:17 ` [PATCH 24/28] drm/amd/display: Add more CRC " Alex Hung
2026-10-27 23:17 ` [PATCH 25/28] drm/amd/display: Add more connector " Alex Hung
2026-10-27 23:17 ` [PATCH 26/28] drm/amd/display: Update alt shared lib to use dynamic state Alex Hung
2026-10-27 23:17 ` [PATCH 27/28] drm/amd/display: [FW Promotion] Release 0.1.82.0 Alex Hung
2026-10-27 23:17 ` [PATCH 28/28] drm/amd/display: Promote DC to 3.2.405 Alex Hung
2026-10-30 15:42 ` [PATCH 00/28] DC Patches Oct 27, 2026 Leo Li
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.