* [PATCH 00/24] DC Patches for 8 June 2026
@ 2026-06-04 14:51 Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 01/24] drm/amd/display: Skip PHY SSC reduction on some 8K panels Aurabindo Pillai
` (24 more replies)
0 siblings, 25 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:51 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
Summary:
* Display connectivity & HPD:
- Retry link detection on resume, boot, and hotplug
- Refactor HPD RX to use handle_hpd_irq_helper with detect reason
- Always create delayed HPD work queue
- Restore periodic detection for DCN35
* DCN42B support:
- Fix DCN42B version detection
- Add DCN42B to dml21_translation_helper
* KUnit testing infrastructure:
- Add KUnit tests for amdgpu_dm_pp_smu, amdgpu_dm_mst_types,
and writeback connector
- Extract HDCP and DPRX CRC transition helpers for KUnit
- Export symbols for KUnit test modules
- Enable warnings as errors for KUnit tests
* Fixes & cleanups:
- Fix compressed buffer config routine waiting time
- Fix incorrect logic in CRC source handling
- Fix writeback format loop and variable init
- Fix max dispclk_khz/dppclk_khz double 1000
- Remove duplicate pp_rn_set_wm_ranges
- Remove dead code in dm_dp_mst_get_modes
- Remove redundant code in amdgpu_dm_replay
- Skip PHY SSC reduction on some 8K panels
- Temp disable repeater FGCG as workaround
- Deprecate DMUB register offload functionality
- TEST_HARNESS FSN could be 0
* Firmware:
- DMUB FW promotion to 0.1.62.0
---
Alex Hung (11):
drm/amd/display: Fix writeback format loop and variable init
drm/amd/display: Add KUnit tests for writeback connector
drm/amd/display: remove redundant code in amdgpu_dm_replay
drm/amd/display: Enable warnings as errors for KUnit tests
drm/amd/display: Remove dead code in dm_dp_mst_get_modes
drm/amd/display: Add KUnit tests for amdgpu_dm_mst_types
drm/amd/display: Fix incorrect logic in CRC source handling
drm/amd/display: Extract DPRX CRC transition helpers for KUnit testing
drm/amd/display: Extract HDCP testable helpers for KUnit
drm/amd/display: Remove duplicate pp_rn_set_wm_ranges
drm/amd/display: Add KUnit tests for amdgpu_dm_pp_smu
Antonio Quartulli (1):
drm/amd/display: fix compressed buffer config routine waiting time
Austin Zheng (1):
drm/amd/display: Deprecate DMUB register offload functionality
Charlene Liu (1):
drm/amd/display: fix max dispclk_khz/dppclk_khz double 1000
ChunTao Tso (1):
drm/amd/display: TEST_HARNESS FSN could be 0
Ivan Lipski (1):
drm/amd/display: Restore periodic detection for DCN35
Ovidiu Bunea (1):
drm/amd/display: Temp disable repeater FGCG as workaround
Roman Li (1):
drm/amd/display: Skip PHY SSC reduction on some 8K panels
Taimur Hassan (1):
drm/amd/display: Promote DC to 3.2.385
Timur Kristóf (5):
drm/amd/display: Add detect reason to handle_hpd_irq_helper
drm/amd/display: Use handle_hpd_irq_helper for HPD RX
drm/amd/display: Always create delayed HPD work queue
drm/amd/display: Retry link detection on hotplug
drm/amd/display: Retry link detection on resume and boot
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 224 ++++++++----
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 16 +
.../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 100 ++++--
.../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 6 +
.../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 115 ++++--
.../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 12 +
.../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 +-
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 25 +-
.../display/amdgpu_dm/amdgpu_dm_mst_types.h | 6 +
.../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 21 +-
.../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h | 16 +
.../amd/display/amdgpu_dm/amdgpu_dm_replay.c | 7 +-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c | 15 +-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_wb.h | 13 +
.../amd/display/amdgpu_dm/tests/.kunitconfig | 3 +
.../drm/amd/display/amdgpu_dm/tests/Makefile | 4 +
.../amdgpu_dm/tests/amdgpu_dm_crc_test.c | 122 +++++++
.../amdgpu_dm/tests/amdgpu_dm_hdcp_test.c | 297 +++++++++++++++-
.../tests/amdgpu_dm_mst_types_test.c | 124 +++++++
.../amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c | 241 +++++++++++++
.../amdgpu_dm/tests/amdgpu_dm_wb_test.c | 336 ++++++++++++++++++
.../display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 -
.../dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 2 -
.../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 2 +
drivers/gpu/drm/amd/display/dc/dc.h | 6 +-
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 12 -
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 9 -
drivers/gpu/drm/amd/display/dc/dc_helper.c | 226 ------------
.../amd/display/dc/dccg/dcn42/dcn42_dccg.c | 6 +-
drivers/gpu/drm/amd/display/dc/dm_services.h | 4 -
.../dc/dml2_0/dml21/dml21_wrapper_fpu.c | 8 +-
.../amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c | 5 -
.../display/dc/hubbub/dcn31/dcn31_hubbub.c | 8 +-
.../amd/display/dc/hubp/dcn42/dcn42_hubp.c | 6 +
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 3 -
.../amd/display/dc/hwss/dcn42/dcn42_hwseq.c | 9 +-
.../gpu/drm/amd/display/dc/inc/reg_helper.h | 19 -
.../drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c | 4 -
.../amd/display/dc/optc/dcn10/dcn10_optc.c | 5 -
.../amd/display/dc/optc/dcn20/dcn20_optc.c | 5 -
.../amd/display/dc/optc/dcn31/dcn31_optc.c | 5 -
.../amd/display/dc/optc/dcn314/dcn314_optc.c | 5 -
.../amd/display/dc/optc/dcn32/dcn32_optc.c | 5 -
.../amd/display/dc/optc/dcn35/dcn35_optc.c | 5 -
.../amd/display/dc/optc/dcn401/dcn401_optc.c | 5 -
.../dc/resource/dcn35/dcn35_resource.c | 1 -
.../dc/resource/dcn351/dcn351_resource.c | 1 -
.../dc/resource/dcn36/dcn36_resource.c | 1 -
.../dc/resource/dcn42/dcn42_resource.c | 1 +
.../amd/display/modules/power/power_replay.c | 9 +-
50 files changed, 1576 insertions(+), 519 deletions(-)
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
--
2.54.0
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 01/24] drm/amd/display: Skip PHY SSC reduction on some 8K panels
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
@ 2026-06-04 14:51 ` Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 02/24] drm/amd/display: TEST_HARNESS FSN could be 0 Aurabindo Pillai
` (23 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:51 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
From: Roman Li <Roman.Li@amd.com>
[Why]
Some 8K displays cannot tolerate the reduced phy ssc value
at high link utilization and show corruption or black screen.
[How]
Add an EDID panel-id quirk to utilize existing skip_phy_ssc_reduction flag.
To pass the link into the quirk handler, change the signature of
apply_edid_quirks() to take link as an argument. The dev local in
dm_helpers_parse_edid_caps() becomes unused and is removed.
Fixes: 5fa62c87cffd ("drm/amd/display: Add option to disable PHY SSC reduction on transmitter enable")
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Roman Li <Roman.Li@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 844fd403795d..a2d0bb34e639 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -95,8 +95,11 @@ static u32 edid_extract_panel_id(struct edid *edid)
(u32)EDID_PRODUCT_ID(edid);
}
-static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct dc_edid_caps *edid_caps)
+static void apply_edid_quirks(struct dc_link *link, struct edid *edid,
+ struct dc_edid_caps *edid_caps)
{
+ struct amdgpu_dm_connector *aconnector = link->priv;
+ struct drm_device *dev = aconnector->base.dev;
uint32_t panel_id = edid_extract_panel_id(edid);
switch (panel_id) {
@@ -126,6 +129,11 @@ static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct
drm_dbg_driver(dev, "Disabling VSC on monitor with panel id %X\n", panel_id);
edid_caps->panel_patch.disable_colorimetry = true;
break;
+ /* Workaround for monitors that get corrupted by the PHY SSC reduction */
+ case drm_edid_encode_panel_id('D', 'E', 'L', 0x4147):
+ drm_dbg_driver(dev, "Skip PHY SSC reduction on panel id %X\n", panel_id);
+ link->wa_flags.skip_phy_ssc_reduction = true;
+ break;
default:
return;
}
@@ -147,7 +155,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
{
struct amdgpu_dm_connector *aconnector = link->priv;
struct drm_connector *connector = &aconnector->base;
- struct drm_device *dev = connector->dev;
struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid : NULL;
struct cea_sad *sads;
int sad_count = -1;
@@ -188,7 +195,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
edid_caps->frl_dsc_max_frl_rate, edid_caps->frl_dsc_total_chunk_kbytes);
}
- apply_edid_quirks(dev, edid_buf, edid_caps);
+ apply_edid_quirks(link, edid_buf, edid_caps);
sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
if (sad_count <= 0)
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 02/24] drm/amd/display: TEST_HARNESS FSN could be 0
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 01/24] drm/amd/display: Skip PHY SSC reduction on some 8K panels Aurabindo Pillai
@ 2026-06-04 14:51 ` Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 03/24] drm/amd/display: Deprecate DMUB register offload functionality Aurabindo Pillai
` (22 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:51 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, ChunTao Tso, Robin Chen
From: ChunTao Tso <ChunTao.Tso@amd.com>
The frame skipping number could be 0 if needed.
Reviewed-by: Robin Chen <robin.chen@amd.com>
Signed-off-by: ChunTao Tso <ChunTao.Tso@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
drivers/gpu/drm/amd/display/modules/power/power_replay.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_replay.c b/drivers/gpu/drm/amd/display/modules/power/power_replay.c
index 983be9759e74..e782501442c4 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_replay.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_replay.c
@@ -175,11 +175,10 @@ static bool mod_power_update_replay_active_status(unsigned int active_replay_eve
if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
*coasting_vtotal =
link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
- if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
- ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS] <= 0xFFFF);
- *frame_skip_number =
- (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
- }
+
+ ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS] <= 0xFFFF);
+ *frame_skip_number =
+ (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
if (active_replay_events & (replay_event_test_harness_enable_replay)) {
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 03/24] drm/amd/display: Deprecate DMUB register offload functionality
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 01/24] drm/amd/display: Skip PHY SSC reduction on some 8K panels Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 02/24] drm/amd/display: TEST_HARNESS FSN could be 0 Aurabindo Pillai
@ 2026-06-04 14:51 ` Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 04/24] drm/amd/display: Temp disable repeater FGCG as workaround Aurabindo Pillai
` (21 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:51 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,
Nicholas Kazlauskas, Austin Zheng
From: Austin Zheng <austin.zheng@amd.com>
[Why]
The DMUB register offload feature should no longer be used.
This was originally a debug feature for DCN21.
No longer applicable to the DMUB programming model.
[How]
Remove DMUB register offload infrastructure including helper
functions, structures, debug options, and register sequence macros.
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Austin Zheng <Austin.Zheng@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 -
drivers/gpu/drm/amd/display/dc/dc.h | 3 -
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 12 -
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 9 -
drivers/gpu/drm/amd/display/dc/dc_helper.c | 226 ------------------
drivers/gpu/drm/amd/display/dc/dm_services.h | 4 -
.../amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c | 5 -
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 3 -
.../gpu/drm/amd/display/dc/inc/reg_helper.h | 19 --
.../drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c | 4 -
.../amd/display/dc/optc/dcn10/dcn10_optc.c | 5 -
.../amd/display/dc/optc/dcn20/dcn20_optc.c | 5 -
.../amd/display/dc/optc/dcn31/dcn31_optc.c | 5 -
.../amd/display/dc/optc/dcn314/dcn314_optc.c | 5 -
.../amd/display/dc/optc/dcn32/dcn32_optc.c | 5 -
.../amd/display/dc/optc/dcn35/dcn35_optc.c | 5 -
.../amd/display/dc/optc/dcn401/dcn401_optc.c | 5 -
.../dc/resource/dcn35/dcn35_resource.c | 1 -
.../dc/resource/dcn351/dcn351_resource.c | 1 -
.../dc/resource/dcn36/dcn36_resource.c | 1 -
20 files changed, 330 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 6c1e7e13f039..46993b5ae688 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -13913,13 +13913,6 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
}
#endif
- if (ctx->dmub_srv &&
- ctx->dmub_srv->reg_helper_offload.gather_in_progress &&
- !ctx->dmub_srv->reg_helper_offload.should_burst_write) {
- ASSERT(false);
- return 0;
- }
-
amdgpu_dm_exit_ips_for_hw_access(ctx->dc);
value = cgs_read_register(ctx->cgs_device, address);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 82d02ebbd829..d5d9d56fbcb8 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1129,8 +1129,6 @@ struct dc_debug_options {
unsigned int force_fclk_khz;
bool enable_tri_buf;
bool ips_disallow_entry;
- bool dmub_offload_enabled;
- bool dmcub_emulation;
bool disable_idle_power_optimizations;
unsigned int mall_size_override;
unsigned int mall_additional_timer_percent;
@@ -1332,7 +1330,6 @@ struct dc_init_data {
enum dce_environment dce_environment;
struct dmub_offload_funcs *dmub_if;
- struct dc_reg_helper_state *dmub_offload;
struct dc_config flags;
uint64_t log_mask;
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 ea0210216d9e..66836b38d0e1 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -518,9 +518,6 @@ void dc_dmub_srv_query_caps_cmd(struct dc_dmub_srv *dc_dmub_srv)
{
union dmub_rb_cmd cmd = { 0 };
- if (dc_dmub_srv->ctx->dc->debug.dmcub_emulation)
- return;
-
memset(&cmd, 0, sizeof(cmd));
/* Prepare fw command */
@@ -1302,9 +1299,6 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait)
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
return true;
- if (dc_dmub_srv->ctx->dc->debug.dmcub_emulation)
- return true;
-
dc_ctx = dc_dmub_srv->ctx;
if (wait) {
@@ -1345,9 +1339,6 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle)
struct dc_dmub_srv *dc_dmub_srv;
union dmub_rb_cmd cmd = {0};
- if (dc->debug.dmcub_emulation)
- return;
-
if (!dc->ctx->dmub_srv || !dc->ctx->dmub_srv->dmub)
return;
@@ -1466,9 +1457,6 @@ static void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
struct dc_dmub_srv *dc_dmub_srv;
uint32_t rcg_exit_count = 0, ips1_exit_count = 0, ips2_exit_count = 0, ips1z8_exit_count = 0;
- if (dc->debug.dmcub_emulation)
- return;
-
if (!dc->ctx->dmub_srv || !dc->ctx->dmub_srv->dmub)
return;
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 ebcaf49e5961..5d399e6a8345 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -37,17 +37,8 @@ struct dc_crtc_timing;
struct dc_state;
struct dc_surface_update;
-struct dc_reg_helper_state {
- bool gather_in_progress;
- uint32_t same_addr_count;
- bool should_burst_write;
- union dmub_rb_cmd cmd_data;
- unsigned int reg_seq_count;
-};
-
struct dc_dmub_srv {
struct dmub_srv *dmub;
- struct dc_reg_helper_state reg_helper_offload;
struct dc_context *ctx;
void *dm;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
index 0e0165764a57..cc7fea613d9e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
@@ -39,53 +39,6 @@
#define DC_LOGGER \
ctx->logger
-static inline void submit_dmub_read_modify_write(
- struct dc_reg_helper_state *offload,
- const struct dc_context *ctx)
-{
- struct dmub_rb_cmd_read_modify_write *cmd_buf = &offload->cmd_data.read_modify_write;
-
- offload->should_burst_write =
- (offload->same_addr_count == (DMUB_READ_MODIFY_WRITE_SEQ__MAX - 1));
- cmd_buf->header.payload_bytes =
- sizeof(struct dmub_cmd_read_modify_write_sequence) * offload->reg_seq_count;
-
- dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
-
- memset(cmd_buf, 0, sizeof(*cmd_buf));
-
- offload->reg_seq_count = 0;
- offload->same_addr_count = 0;
-}
-
-static inline void submit_dmub_burst_write(
- struct dc_reg_helper_state *offload,
- const struct dc_context *ctx)
-{
- struct dmub_rb_cmd_burst_write *cmd_buf = &offload->cmd_data.burst_write;
-
- cmd_buf->header.payload_bytes =
- sizeof(uint32_t) * offload->reg_seq_count;
-
- dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
-
- memset(cmd_buf, 0, sizeof(*cmd_buf));
-
- offload->reg_seq_count = 0;
-}
-
-static inline void submit_dmub_reg_wait(
- struct dc_reg_helper_state *offload,
- const struct dc_context *ctx)
-{
- struct dmub_rb_cmd_reg_wait *cmd_buf = &offload->cmd_data.reg_wait;
-
- dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
-
- memset(cmd_buf, 0, sizeof(*cmd_buf));
- offload->reg_seq_count = 0;
-}
-
struct dc_reg_value_masks {
uint32_t value;
uint32_t mask;
@@ -127,98 +80,6 @@ static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask,
}
}
-static void dmub_flush_buffer_execute(
- struct dc_reg_helper_state *offload,
- const struct dc_context *ctx)
-{
- submit_dmub_read_modify_write(offload, ctx);
-}
-
-static void dmub_flush_burst_write_buffer_execute(
- struct dc_reg_helper_state *offload,
- const struct dc_context *ctx)
-{
- submit_dmub_burst_write(offload, ctx);
-}
-
-static bool dmub_reg_value_burst_set_pack(const struct dc_context *ctx, uint32_t addr,
- uint32_t reg_val)
-{
- struct dc_reg_helper_state *offload = &ctx->dmub_srv->reg_helper_offload;
- struct dmub_rb_cmd_burst_write *cmd_buf = &offload->cmd_data.burst_write;
-
- /* flush command if buffer is full */
- if (offload->reg_seq_count == DMUB_BURST_WRITE_VALUES__MAX)
- dmub_flush_burst_write_buffer_execute(offload, ctx);
-
- if (offload->cmd_data.cmd_common.header.type == DMUB_CMD__REG_SEQ_BURST_WRITE &&
- addr != cmd_buf->addr) {
- dmub_flush_burst_write_buffer_execute(offload, ctx);
- return false;
- }
-
- cmd_buf->header.type = DMUB_CMD__REG_SEQ_BURST_WRITE;
- cmd_buf->header.sub_type = 0;
- cmd_buf->addr = addr;
- cmd_buf->write_values[offload->reg_seq_count] = reg_val;
- offload->reg_seq_count++;
-
- return true;
-}
-
-static uint32_t dmub_reg_value_pack(const struct dc_context *ctx, uint32_t addr,
- struct dc_reg_value_masks *field_value_mask)
-{
- struct dc_reg_helper_state *offload = &ctx->dmub_srv->reg_helper_offload;
- struct dmub_rb_cmd_read_modify_write *cmd_buf = &offload->cmd_data.read_modify_write;
- struct dmub_cmd_read_modify_write_sequence *seq;
-
- /* flush command if buffer is full */
- if (offload->cmd_data.cmd_common.header.type != DMUB_CMD__REG_SEQ_BURST_WRITE &&
- offload->reg_seq_count == DMUB_READ_MODIFY_WRITE_SEQ__MAX)
- dmub_flush_buffer_execute(offload, ctx);
-
- if (offload->should_burst_write) {
- if (dmub_reg_value_burst_set_pack(ctx, addr, field_value_mask->value))
- return field_value_mask->value;
- else
- offload->should_burst_write = false;
- }
-
- /* pack commands */
- cmd_buf->header.type = DMUB_CMD__REG_SEQ_READ_MODIFY_WRITE;
- cmd_buf->header.sub_type = 0;
- seq = &cmd_buf->seq[offload->reg_seq_count];
-
- if (offload->reg_seq_count) {
- if (cmd_buf->seq[offload->reg_seq_count - 1].addr == addr)
- offload->same_addr_count++;
- else
- offload->same_addr_count = 0;
- }
-
- seq->addr = addr;
- seq->modify_mask = field_value_mask->mask;
- seq->modify_value = field_value_mask->value;
- offload->reg_seq_count++;
-
- return field_value_mask->value;
-}
-
-static void dmub_reg_wait_done_pack(const struct dc_context *ctx, uint32_t addr,
- uint32_t mask, uint32_t shift, uint32_t condition_value, uint32_t time_out_us)
-{
- struct dc_reg_helper_state *offload = &ctx->dmub_srv->reg_helper_offload;
- struct dmub_rb_cmd_reg_wait *cmd_buf = &offload->cmd_data.reg_wait;
-
- cmd_buf->header.type = DMUB_CMD__REG_REG_WAIT;
- cmd_buf->header.sub_type = 0;
- cmd_buf->reg_wait.addr = addr;
- cmd_buf->reg_wait.condition_field_value = mask & (condition_value << shift);
- cmd_buf->reg_wait.mask = mask;
- cmd_buf->reg_wait.time_out_us = time_out_us;
-}
-
uint32_t generic_reg_update_ex(const struct dc_context *ctx,
uint32_t addr, int n,
uint8_t shift1, uint32_t mask1, uint32_t field_value1,
@@ -235,11 +96,6 @@ uint32_t generic_reg_update_ex(const struct dc_context *ctx,
va_end(ap);
- if (ctx->dmub_srv &&
- ctx->dmub_srv->reg_helper_offload.gather_in_progress)
- return dmub_reg_value_pack(ctx, addr, &field_value_mask);
- /* todo: return void so we can decouple code running in driver from register states */
-
/* mmio write directly */
reg_val = dm_read_reg(ctx, addr);
reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
@@ -265,12 +121,6 @@ uint32_t generic_reg_set_ex(const struct dc_context *ctx,
/* mmio write directly */
reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
- if (ctx->dmub_srv &&
- ctx->dmub_srv->reg_helper_offload.gather_in_progress) {
- return dmub_reg_value_burst_set_pack(ctx, addr, reg_val);
- /* todo: return void so we can decouple code running in driver from register states */
- }
-
dm_write_reg(ctx, addr, reg_val);
return reg_val;
}
@@ -434,13 +284,6 @@ void generic_reg_wait(const struct dc_context *ctx,
uint32_t reg_val;
unsigned int i;
- if (ctx->dmub_srv &&
- ctx->dmub_srv->reg_helper_offload.gather_in_progress) {
- dmub_reg_wait_done_pack(ctx, addr, mask, shift, condition_value,
- delay_between_poll_us * time_out_num_tries);
- return;
- }
-
/*
* Something is terribly wrong if time out is > 3000ms.
* 3000ms is the maximum time needed for SMU to pass values back.
@@ -491,12 +334,6 @@ uint32_t generic_read_indirect_reg(const struct dc_context *ctx,
{
uint32_t value = 0;
- // when reg read, there should not be any offload.
- if (ctx->dmub_srv &&
- ctx->dmub_srv->reg_helper_offload.gather_in_progress) {
- ASSERT(false);
- }
-
dm_write_reg(ctx, addr_index, index);
value = dm_read_reg(ctx, addr_data);
@@ -624,69 +461,6 @@ uint32_t generic_indirect_reg_get_sync(const struct dc_context *ctx,
return value;
}
-void reg_sequence_start_gather(const struct dc_context *ctx)
-{
- /* if reg sequence is supported and enabled, set flag to
- * indicate we want to have REG_SET, REG_UPDATE macro build
- * reg sequence command buffer rather than MMIO directly.
- */
-
- if (ctx->dmub_srv && ctx->dc->debug.dmub_offload_enabled) {
- struct dc_reg_helper_state *offload =
- &ctx->dmub_srv->reg_helper_offload;
-
- /* caller sequence mismatch. need to debug caller. offload will not work!!! */
- ASSERT(!offload->gather_in_progress);
-
- offload->gather_in_progress = true;
- }
-}
-
-void reg_sequence_start_execute(const struct dc_context *ctx)
-{
- struct dc_reg_helper_state *offload;
-
- if (!ctx->dmub_srv)
- return;
-
- offload = &ctx->dmub_srv->reg_helper_offload;
-
- if (offload && offload->gather_in_progress) {
- offload->gather_in_progress = false;
- offload->should_burst_write = false;
- switch (offload->cmd_data.cmd_common.header.type) {
- case DMUB_CMD__REG_SEQ_READ_MODIFY_WRITE:
- submit_dmub_read_modify_write(offload, ctx);
- break;
- case DMUB_CMD__REG_REG_WAIT:
- submit_dmub_reg_wait(offload, ctx);
- break;
- case DMUB_CMD__REG_SEQ_BURST_WRITE:
- submit_dmub_burst_write(offload, ctx);
- break;
- default:
- return;
- }
- }
-}
-
-void reg_sequence_wait_done(const struct dc_context *ctx)
-{
- /* callback to DM to poll for last submission done*/
- struct dc_reg_helper_state *offload;
-
- if (!ctx->dmub_srv)
- return;
-
- offload = &ctx->dmub_srv->reg_helper_offload;
-
- if (offload &&
- ctx->dc->debug.dmub_offload_enabled &&
- !ctx->dc->debug.dmcub_emulation) {
- dc_dmub_srv_wait_for_idle(ctx->dmub_srv, DM_DMUB_WAIT_TYPE_WAIT, NULL);
- }
-}
-
char *dce_version_to_string(const int version)
{
switch (version) {
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h
index 8b062b011fc6..2cf4bcb03cb0 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services.h
@@ -127,10 +127,6 @@ uint32_t generic_reg_update_ex(const struct dc_context *ctx,
struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub);
void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv);
-void reg_sequence_start_gather(const struct dc_context *ctx);
-void reg_sequence_start_execute(const struct dc_context *ctx);
-void reg_sequence_wait_done(const struct dc_context *ctx);
-
#define FD(reg_field) reg_field ## __SHIFT, \
reg_field ## _MASK
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c
index 53b21adc6267..9788628cf0ad 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c
@@ -397,8 +397,6 @@ void dpp1_cm_program_regamma_lut(struct dpp *dpp_base,
uint32_t i;
struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
- REG_SEQ_START();
-
for (i = 0 ; i < num; i++) {
REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg);
REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg);
@@ -408,9 +406,6 @@ void dpp1_cm_program_regamma_lut(struct dpp *dpp_base,
REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].delta_green_reg);
REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg);
}
-
- REG_SEQ_SUBMIT();
- REG_SEQ_WAIT_DONE();
}
void dpp1_cm_configure_regamma_lut(
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index 8f9038fec0f7..01027d120cb0 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -581,9 +581,6 @@ void dcn35_power_down_on_boot(struct dc *dc)
bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable)
{
- if (dc->debug.dmcub_emulation)
- return true;
-
if (enable) {
uint32_t num_active_edp = 0;
int i;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h
index 7a1ecb8d986f..6d15ccdc7f87 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h
@@ -536,23 +536,4 @@ uint32_t generic_indirect_reg_update_ex_sync(const struct dc_context *ctx,
uint8_t shift1, uint32_t mask1, uint32_t field_value1,
...);
-/* register offload macros
- *
- * instead of MMIO to register directly, in some cases we want
- * to gather register sequence and execute the register sequence
- * from another thread so we optimize time required for lengthy ops
- */
-
-/* start gathering register sequence */
-#define REG_SEQ_START() \
- reg_sequence_start_gather(CTX)
-
-/* start execution of register sequence gathered since REG_SEQ_START */
-#define REG_SEQ_SUBMIT() \
- reg_sequence_start_execute(CTX)
-
-/* wait for the last REG_SEQ_SUBMIT to finish */
-#define REG_SEQ_WAIT_DONE() \
- reg_sequence_wait_done(CTX)
-
#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c
index fa600593f4c1..0e09d073ab29 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c
@@ -380,7 +380,6 @@ static void mpc20_program_ogam_pwl(
struct dcn20_mpc *mpc20 = TO_DCN20_MPC(mpc);
PERF_TRACE();
- REG_SEQ_START();
for (i = 0 ; i < num; i++) {
REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
@@ -395,9 +394,6 @@ static void mpc20_program_ogam_pwl(
MPCC_OGAM_LUT_DATA, rgb[i].delta_blue_reg);
}
- REG_SEQ_SUBMIT();
- PERF_TRACE();
- REG_SEQ_WAIT_DONE();
PERF_TRACE();
}
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
index e6426ccee2d8..cf8e22289d6a 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
@@ -539,16 +539,11 @@ static bool optc1_enable_crtc(struct timing_generator *optc)
REG_UPDATE(CONTROL,
VTG0_ENABLE, 1);
- REG_SEQ_START();
-
/* Enable CRTC */
REG_UPDATE_2(OTG_CONTROL,
OTG_DISABLE_POINT_CNTL, 3,
OTG_MASTER_EN, 1);
- REG_SEQ_SUBMIT();
- REG_SEQ_WAIT_DONE();
-
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
index c558b1d633f3..73cc8a713556 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
@@ -63,16 +63,11 @@ bool optc2_enable_crtc(struct timing_generator *optc)
REG_UPDATE(CONTROL,
VTG0_ENABLE, 1);
- REG_SEQ_START();
-
/* Enable CRTC */
REG_UPDATE_2(OTG_CONTROL,
OTG_DISABLE_POINT_CNTL, 3,
OTG_MASTER_EN, 1);
- REG_SEQ_SUBMIT();
- REG_SEQ_WAIT_DONE();
-
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
index 98aaa22ce81c..3ace83e1b50f 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
@@ -105,16 +105,11 @@ static bool optc31_enable_crtc(struct timing_generator *optc)
REG_UPDATE(CONTROL,
VTG0_ENABLE, 1);
- REG_SEQ_START();
-
/* Enable CRTC */
REG_UPDATE_2(OTG_CONTROL,
OTG_DISABLE_POINT_CNTL, 2,
OTG_MASTER_EN, 1);
- REG_SEQ_SUBMIT();
- REG_SEQ_WAIT_DONE();
-
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
index a7cf34937b2f..7250478a5092 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
@@ -115,16 +115,11 @@ static bool optc314_enable_crtc(struct timing_generator *optc)
REG_UPDATE(CONTROL,
VTG0_ENABLE, 1);
- REG_SEQ_START();
-
/* Enable CRTC */
REG_UPDATE_2(OTG_CONTROL,
OTG_DISABLE_POINT_CNTL, 2,
OTG_MASTER_EN, 1);
- REG_SEQ_SUBMIT();
- REG_SEQ_WAIT_DONE();
-
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
index 07895d5f4dfa..f9e05efcad98 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
@@ -155,16 +155,11 @@ static bool optc32_enable_crtc(struct timing_generator *optc)
REG_UPDATE(CONTROL,
VTG0_ENABLE, 1);
- REG_SEQ_START();
-
/* Enable CRTC */
REG_UPDATE_2(OTG_CONTROL,
OTG_DISABLE_POINT_CNTL, 2,
OTG_MASTER_EN, 1);
- REG_SEQ_SUBMIT();
- REG_SEQ_WAIT_DONE();
-
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
index 62f45c156c32..9b7f9d5bbfb3 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
@@ -122,16 +122,11 @@ static bool optc35_enable_crtc(struct timing_generator *optc)
REG_UPDATE(CONTROL,
VTG0_ENABLE, 1);
- REG_SEQ_START();
-
/* Enable CRTC */
REG_UPDATE_2(OTG_CONTROL,
OTG_DISABLE_POINT_CNTL, 2,
OTG_MASTER_EN, 1);
- REG_SEQ_SUBMIT();
- REG_SEQ_WAIT_DONE();
-
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
index a6d76f451cf8..5fcdd74eb4a0 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
@@ -189,16 +189,11 @@ bool optc401_enable_crtc(struct timing_generator *optc)
REG_UPDATE(CONTROL,
VTG0_ENABLE, 1);
- REG_SEQ_START();
-
/* Enable CRTC */
REG_UPDATE_2(OTG_CONTROL,
OTG_DISABLE_POINT_CNTL, 2,
OTG_MASTER_EN, 1);
- REG_SEQ_SUBMIT();
- REG_SEQ_WAIT_DONE();
-
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index ec92e8f7d173..baf00942b8f3 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -819,7 +819,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.enable_hpo_pg_support = false,
.enable_single_display_2to1_odm_policy = true,
.disable_idle_power_optimizations = false,
- .dmcub_emulation = false,
.disable_boot_optimizations = false,
.disable_unbounded_requesting = false,
.disable_mem_low_power = false,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index 4d2d26d64a56..75a0a3dc3052 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -799,7 +799,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.enable_hpo_pg_support = false,
.enable_single_display_2to1_odm_policy = true,
.disable_idle_power_optimizations = false,
- .dmcub_emulation = false,
.disable_boot_optimizations = false,
.disable_unbounded_requesting = false,
.disable_mem_low_power = false,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
index 4bab31fa2b96..8e84abdff57a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
@@ -806,7 +806,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.enable_hpo_pg_support = false,
.enable_single_display_2to1_odm_policy = true,
.disable_idle_power_optimizations = false,
- .dmcub_emulation = false,
.disable_boot_optimizations = false,
.disable_unbounded_requesting = false,
.disable_mem_low_power = false,
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 04/24] drm/amd/display: Temp disable repeater FGCG as workaround
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (2 preceding siblings ...)
2026-06-04 14:51 ` [PATCH 03/24] drm/amd/display: Deprecate DMUB register offload functionality Aurabindo Pillai
@ 2026-06-04 14:51 ` Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 05/24] drm/amd/display: Fix writeback format loop and variable init Aurabindo Pillai
` (20 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:51 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, Ovidiu Bunea,
Nicholas Kazlauskas
From: Ovidiu Bunea <ovidiu.bunea@amd.com>
[why & how]
There is an issue that is seemingly limited to DCN42 where systems with
IOMMU enabled will hang during reboot stress testing. The hang happens shortly
after DCN PG exit happens and HUBP is programmed for the first flip, but before
the first surface address is latched. Testing has shown that disabling
DCCG_GLOBAL_FGCG_REP_DIS, HUBP_FGCG_REP_DIS, and DCFCLK_GATE_DIS can mask this
issue.
Disable FGCG for these three repeater bits to avoid issue while debug is on-going.
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Ovidiu Bunea <ovidiu.bunea@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
drivers/gpu/drm/amd/display/dc/dc.h | 1 +
drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c | 6 +++++-
drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c | 6 ++++++
drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c | 9 ++++++++-
.../drm/amd/display/dc/resource/dcn42/dcn42_resource.c | 1 +
5 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index d5d9d56fbcb8..d74776802418 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1288,6 +1288,7 @@ struct dc_debug_options {
unsigned int min_deep_sleep_dcfclk_khz;
unsigned int force_odm2to1_for_edp_pixclk_mhz;
bool enable_replay_esd_recovery;
+ uint8_t iommu_mismatch_temp_wka;
};
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
index e57242f8bc12..adc453c81831 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
@@ -81,8 +81,12 @@ void dccg42_enable_global_fgcg(struct dccg *dccg, bool value)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
- if (dccg->ctx->dc->debug.disable_clock_gate)
+ /* Temporary workaround for IOMMU mismatch issue.
+ * Fine grain control via bit2 of debug flag.
+ */
+ if (dccg->ctx->dc->debug.disable_clock_gate || (dccg->ctx->dc->debug.iommu_mismatch_temp_wka & 0x4))
value = false;
+
REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, !value);
}
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
index e4602c3ddc66..57de98444f6c 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
@@ -20,6 +20,12 @@ static void hubp42_set_fgcg(struct hubp *hubp, bool enable)
{
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+ /* Temporary workaround for IOMMU mismatch issue.
+ * Fine grain control via bit1 of debug flag.
+ */
+ if (hubp->ctx->dc->debug.iommu_mismatch_temp_wka & 0x2)
+ enable = false;
+
REG_UPDATE(HUBP_CLK_CNTL, HUBP_FGCG_REP_DIS, !enable);
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
index 664004cadf10..96e0133880e1 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
@@ -70,6 +70,7 @@ void dcn42_init_hw(struct dc *dc)
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
bool dchub_ref_freq_changed;
int current_dchub_ref_freq = 0;
+ uint8_t dcfclk_gate_dis_value = 0;
if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
@@ -243,7 +244,13 @@ void dcn42_init_hw(struct dc *dc)
/* enable all DCN clock gating */
REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
- REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+ /* Temporary workaround for IOMMU mismatch issue.
+ * Fine grain control via bit0 of debug flag.
+ */
+ if (dc->debug.iommu_mismatch_temp_wka & 0x1)
+ dcfclk_gate_dis_value = 1;
+
+ REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, dcfclk_gate_dis_value);
}
dcn401_setup_hpo_hw_control(hws, true);
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
index 7de12b16d7ad..eb7fe5d70264 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
@@ -801,6 +801,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.replay_skip_crtc_disabled = true,
.psr_skip_crtc_disable = true,
.force_odm2to1_for_edp_pixclk_mhz = 0, // disable the policy for now
+ .iommu_mismatch_temp_wka = 0x7,
};
static const struct dc_check_config config_defaults = {
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 05/24] drm/amd/display: Fix writeback format loop and variable init
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (3 preceding siblings ...)
2026-06-04 14:51 ` [PATCH 04/24] drm/amd/display: Temp disable repeater FGCG as workaround Aurabindo Pillai
@ 2026-06-04 14:51 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 06/24] drm/amd/display: Add KUnit tests for writeback connector Aurabindo Pillai
` (19 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:51 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
From: Alex Hung <alex.hung@amd.com>
[WHAT]
1. Use ARRAY_SIZE() instead of manual sizeof division for the
format array iteration. Add a break statement to exit the loop
early once a matching format is found.
2. Remove redundant zero initialization of res since all paths
assign before use.
Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
index 110f0173eee6..ead3d0bb052f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
@@ -59,9 +59,11 @@ static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
return -EINVAL;
}
- for (i = 0; i < sizeof(amdgpu_dm_wb_formats) / sizeof(u32); i++) {
- if (fb->format->format == amdgpu_dm_wb_formats[i])
+ for (i = 0; i < ARRAY_SIZE(amdgpu_dm_wb_formats); i++) {
+ if (fb->format->format == amdgpu_dm_wb_formats[i]) {
found = true;
+ break;
+ }
}
if (!found) {
@@ -187,7 +189,7 @@ int amdgpu_dm_wb_connector_init(struct amdgpu_display_manager *dm,
{
struct dc *dc = dm->dc;
struct dc_link *link = dc_get_link_at_index(dc, link_index);
- int res = 0;
+ int res;
wbcon->link = link;
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 06/24] drm/amd/display: Add KUnit tests for writeback connector
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (4 preceding siblings ...)
2026-06-04 14:51 ` [PATCH 05/24] drm/amd/display: Fix writeback format loop and variable init Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 07/24] drm/amd/display: fix max dispclk_khz/dppclk_khz double 1000 Aurabindo Pillai
` (18 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Add KUnit tests for amdgpu_dm_wb_encoder_atomic_check() and
amdgpu_dm_wb_connector_get_modes(). Tests cover null job,
null fb, size mismatch, format validation, and mode count
bounds using DRM KUnit mock devices.
Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c | 7 +-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_wb.h | 13 +
.../drm/amd/display/amdgpu_dm/tests/Makefile | 1 +
.../amdgpu_dm/tests/amdgpu_dm_wb_test.c | 336 ++++++++++++++++++
4 files changed, 355 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
index ead3d0bb052f..058d478a073d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
@@ -29,6 +29,7 @@
#include "amdgpu.h"
#include "amdgpu_dm.h"
#include "amdgpu_dm_wb.h"
+#include "amdgpu_dm_kunit_helpers.h"
#include "amdgpu_display.h"
#include "dc.h"
@@ -40,7 +41,7 @@ static const u32 amdgpu_dm_wb_formats[] = {
DRM_FORMAT_XRGB2101010,
};
-static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
+STATIC_IFN_KUNIT int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
@@ -74,13 +75,15 @@ static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
return 0;
}
+EXPORT_IF_KUNIT(amdgpu_dm_wb_encoder_atomic_check);
-static int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector)
+STATIC_IFN_KUNIT int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector)
{
/* Maximum resolution supported by DWB */
return drm_add_modes_noedid(connector, 3840, 2160);
}
+EXPORT_IF_KUNIT(amdgpu_dm_wb_connector_get_modes);
static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector,
struct drm_writeback_job *job)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.h
index 13d31c857dee..7e9fd7a036fa 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.h
@@ -29,8 +29,21 @@
#include <drm/drm_writeback.h>
+struct amdgpu_display_manager;
+struct amdgpu_dm_wb_connector;
+
int amdgpu_dm_wb_connector_init(struct amdgpu_display_manager *dm,
struct amdgpu_dm_wb_connector *dm_wbcon,
uint32_t link_index);
+#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+
+int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
+int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector);
+#endif
+
#endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
index 768f9bbc50e1..ce1e46acb7af 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_colorop_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_psr_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_replay_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_ism_test.o
+obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_wb_test.o
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
new file mode 100644
index 000000000000..b8ad4b87163a
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * KUnit tests for amdgpu_dm_wb.c
+ *
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_kunit_helpers.h>
+#include <drm/drm_mode.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_writeback.h>
+
+#include "amdgpu_dm_wb.h"
+
+
+/* Helper functions */
+
+static struct drm_crtc_state *alloc_test_crtc_state(struct kunit *test,
+ int hdisplay, int vdisplay)
+{
+ struct drm_crtc_state *crtc_state;
+
+ crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, crtc_state);
+
+ crtc_state->mode.hdisplay = hdisplay;
+ crtc_state->mode.vdisplay = vdisplay;
+
+ return crtc_state;
+}
+
+static struct drm_connector_state *alloc_test_conn_state(struct kunit *test,
+ int fb_width,
+ int fb_height,
+ u32 format)
+{
+ struct drm_connector_state *conn_state;
+ struct drm_writeback_job *job;
+ struct drm_framebuffer *fb;
+ struct drm_format_info *fmt_info;
+
+ conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, conn_state);
+
+ job = kunit_kzalloc(test, sizeof(*job), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, job);
+
+ fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fb);
+
+ fmt_info = kunit_kzalloc(test, sizeof(*fmt_info), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fmt_info);
+
+ fb->width = fb_width;
+ fb->height = fb_height;
+ fmt_info->format = format;
+ fb->format = fmt_info;
+
+ job->fb = fb;
+ conn_state->writeback_job = job;
+
+ return conn_state;
+}
+
+/* Tests for amdgpu_dm_wb_encoder_atomic_check */
+
+/**
+ * dm_test_wb_atomic_check_no_job - Verify early return when no writeback job
+ * @test: KUnit test context
+ *
+ * When conn_state->writeback_job is NULL, no writeback is requested and the
+ * function should return 0 without further validation.
+ */
+static void dm_test_wb_atomic_check_no_job(struct kunit *test)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector_state *conn_state;
+ int ret;
+
+ crtc_state = alloc_test_crtc_state(test, 1920, 1080);
+ conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, conn_state);
+
+ /* No writeback_job — should return 0 */
+ conn_state->writeback_job = NULL;
+ ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+/**
+ * dm_test_wb_atomic_check_no_fb - Verify early return when job has no framebuffer
+ * @test: KUnit test context
+ *
+ * When a writeback job exists but job->fb is NULL, the function should return 0
+ * without validating dimensions or pixel format.
+ */
+static void dm_test_wb_atomic_check_no_fb(struct kunit *test)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector_state *conn_state;
+ struct drm_writeback_job *job;
+ int ret;
+
+ crtc_state = alloc_test_crtc_state(test, 1920, 1080);
+ conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, conn_state);
+
+ job = kunit_kzalloc(test, sizeof(*job), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, job);
+
+ /* writeback_job exists but no fb — should return 0 */
+ job->fb = NULL;
+ conn_state->writeback_job = job;
+ ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+/**
+ * dm_test_wb_atomic_check_valid - Verify success with matching size and supported format
+ * @test: KUnit test context
+ *
+ * When the framebuffer dimensions match the CRTC mode and the pixel format is
+ * in the supported formats list, the function should return 0.
+ */
+static void dm_test_wb_atomic_check_valid(struct kunit *test)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector_state *conn_state;
+ int ret;
+
+ crtc_state = alloc_test_crtc_state(test, 1920, 1080);
+ conn_state = alloc_test_conn_state(test, 1920, 1080,
+ DRM_FORMAT_XRGB2101010);
+
+ ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+/**
+ * dm_test_wb_atomic_check_size_mismatch - Verify rejection when both dimensions differ
+ * @test: KUnit test context
+ *
+ * When both framebuffer width and height differ from the CRTC mode, the
+ * function should return -EINVAL.
+ */
+static void dm_test_wb_atomic_check_size_mismatch(struct kunit *test)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector_state *conn_state;
+ int ret;
+
+ /* FB is 3840x2160 but mode is 1920x1080 */
+ crtc_state = alloc_test_crtc_state(test, 1920, 1080);
+ conn_state = alloc_test_conn_state(test, 3840, 2160,
+ DRM_FORMAT_XRGB2101010);
+
+ ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
+ KUNIT_EXPECT_EQ(test, ret, -EINVAL);
+}
+
+/**
+ * dm_test_wb_atomic_check_width_mismatch - Verify rejection when width alone differs
+ * @test: KUnit test context
+ *
+ * When only the framebuffer width differs from the CRTC mode hdisplay, the
+ * function should return -EINVAL.
+ */
+static void dm_test_wb_atomic_check_width_mismatch(struct kunit *test)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector_state *conn_state;
+ int ret;
+
+ /* Width doesn't match */
+ crtc_state = alloc_test_crtc_state(test, 1920, 1080);
+ conn_state = alloc_test_conn_state(test, 1280, 1080,
+ DRM_FORMAT_XRGB2101010);
+
+ ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
+ KUNIT_EXPECT_EQ(test, ret, -EINVAL);
+}
+
+/**
+ * dm_test_wb_atomic_check_height_mismatch - Verify rejection when height alone differs
+ * @test: KUnit test context
+ *
+ * When only the framebuffer height differs from the CRTC mode vdisplay, the
+ * function should return -EINVAL.
+ */
+static void dm_test_wb_atomic_check_height_mismatch(struct kunit *test)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector_state *conn_state;
+ int ret;
+
+ /* Height doesn't match */
+ crtc_state = alloc_test_crtc_state(test, 1920, 1080);
+ conn_state = alloc_test_conn_state(test, 1920, 720,
+ DRM_FORMAT_XRGB2101010);
+
+ ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
+ KUNIT_EXPECT_EQ(test, ret, -EINVAL);
+}
+
+/**
+ * dm_test_wb_atomic_check_invalid_format - Verify rejection of unsupported pixel format
+ * @test: KUnit test context
+ *
+ * When the framebuffer dimensions match but the pixel format is not in
+ * amdgpu_dm_wb_formats[], the function should return -EINVAL.
+ */
+static void dm_test_wb_atomic_check_invalid_format(struct kunit *test)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_connector_state *conn_state;
+ int ret;
+
+ /* Correct size but unsupported format */
+ crtc_state = alloc_test_crtc_state(test, 1920, 1080);
+ conn_state = alloc_test_conn_state(test, 1920, 1080,
+ DRM_FORMAT_XRGB8888);
+
+ ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
+ KUNIT_EXPECT_EQ(test, ret, -EINVAL);
+}
+
+/* Tests for amdgpu_dm_wb_connector_get_modes using DRM mock */
+
+static const struct drm_connector_funcs dm_wb_test_connector_funcs = {
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .reset = drm_atomic_helper_connector_reset,
+};
+
+/**
+ * dm_test_wb_get_modes_returns_modes - Verify at least one mode is returned
+ * @test: KUnit test context
+ *
+ * Uses a DRM mock connector to verify that amdgpu_dm_wb_connector_get_modes()
+ * populates the connector with at least one display mode.
+ */
+static void dm_test_wb_get_modes_returns_modes(struct kunit *test)
+{
+ struct device *dev;
+ struct drm_device *drm;
+ struct drm_connector *connector;
+ int count;
+
+ dev = drm_kunit_helper_alloc_device(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ drm = __drm_kunit_helper_alloc_drm_device(test, dev,
+ sizeof(*drm), 0,
+ DRIVER_MODESET | DRIVER_ATOMIC);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
+
+ connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, connector);
+
+ drmm_connector_init(drm, connector, &dm_wb_test_connector_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL, NULL);
+
+ count = amdgpu_dm_wb_connector_get_modes(connector);
+
+ /* drm_add_modes_noedid should return at least one mode */
+ KUNIT_EXPECT_GT(test, count, 0);
+}
+
+/**
+ * dm_test_wb_get_modes_bounded_by_max - Verify all modes are within max resolution
+ * @test: KUnit test context
+ *
+ * Uses a DRM mock connector to verify that all modes returned by
+ * amdgpu_dm_wb_connector_get_modes() have hdisplay <= 3840 and
+ * vdisplay <= 2160, matching the DWB hardware maximum.
+ */
+static void dm_test_wb_get_modes_bounded_by_max(struct kunit *test)
+{
+ struct device *dev;
+ struct drm_device *drm;
+ struct drm_connector *connector;
+ struct drm_display_mode *mode;
+
+ dev = drm_kunit_helper_alloc_device(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ drm = __drm_kunit_helper_alloc_drm_device(test, dev,
+ sizeof(*drm), 0,
+ DRIVER_MODESET | DRIVER_ATOMIC);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
+
+ connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, connector);
+
+ drmm_connector_init(drm, connector, &dm_wb_test_connector_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL, NULL);
+
+ amdgpu_dm_wb_connector_get_modes(connector);
+
+ /* All modes must fit within 3840x2160 */
+ list_for_each_entry(mode, &connector->probed_modes, head) {
+ KUNIT_EXPECT_LE(test, mode->hdisplay, 3840);
+ KUNIT_EXPECT_LE(test, mode->vdisplay, 2160);
+ }
+}
+
+static struct kunit_case dm_wb_test_cases[] = {
+ /* amdgpu_dm_wb_encoder_atomic_check */
+ KUNIT_CASE(dm_test_wb_atomic_check_no_job),
+ KUNIT_CASE(dm_test_wb_atomic_check_no_fb),
+ KUNIT_CASE(dm_test_wb_atomic_check_valid),
+ KUNIT_CASE(dm_test_wb_atomic_check_size_mismatch),
+ KUNIT_CASE(dm_test_wb_atomic_check_width_mismatch),
+ KUNIT_CASE(dm_test_wb_atomic_check_height_mismatch),
+ KUNIT_CASE(dm_test_wb_atomic_check_invalid_format),
+ /* amdgpu_dm_wb_connector_get_modes */
+ KUNIT_CASE(dm_test_wb_get_modes_returns_modes),
+ KUNIT_CASE(dm_test_wb_get_modes_bounded_by_max),
+ {}
+};
+
+static struct kunit_suite dm_wb_test_suite = {
+ .name = "amdgpu_dm_wb",
+ .test_cases = dm_wb_test_cases,
+};
+
+kunit_test_suite(dm_wb_test_suite);
+
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_wb");
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 07/24] drm/amd/display: fix max dispclk_khz/dppclk_khz double 1000
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (5 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 06/24] drm/amd/display: Add KUnit tests for writeback connector Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 08/24] drm/amd/display: remove redundant code in amdgpu_dm_replay Aurabindo Pillai
` (17 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Charlene Liu, Dillon Varone,
Dmytro Laktyushkin
From: Charlene Liu <Charlene.Liu@amd.com>
[why]
Fix regresson caused by double roundup and index out of range
Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Reviewed-by: Dmytro Laktyushkin <dmytro.laktyushkin@amd.com>
Signed-off-by: Charlene Liu <Charlene.Liu@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
index de40d7bae252..11fc0b1cd152 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
@@ -118,16 +118,16 @@ static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_sta
context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) {
context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz =
- in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000;
+ in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values - 1];
} else {
- context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000;
+ context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0];
}
if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) {
context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
- in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000;
+ in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values - 1];
} else {
- context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000;
+ context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0];
}
/* get global mall allocation */
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 08/24] drm/amd/display: remove redundant code in amdgpu_dm_replay
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (6 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 07/24] drm/amd/display: fix max dispclk_khz/dppclk_khz double 1000 Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 09/24] drm/amd/display: Enable warnings as errors for KUnit tests Aurabindo Pillai
` (16 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Ray Wu
From: Alex Hung <alex.hung@amd.com>
[WHAT]
In amdgpu_dm_link_setup_replay(), nom_coasting_vtotal was
used only once immediately after in set_replay_coasting_vtotal().
Inline the value directly to remove the no-op alias.
In amdgpu_dm_set_replay_caps(), replace link->ctx->dc->debug
with dc->debug since dc is already assigned as link->ctx->dc,
eliminating a redundant pointer round-trip.
Assisted-by: Copilot:Claude-Sonnet-4.6
Reviewed-by: Ray Wu <ray.wu@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
index 22aa4305d2af..f3cea2aba901 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
@@ -121,8 +121,7 @@ bool amdgpu_dm_set_replay_caps(struct dc_link *link, struct amdgpu_dm_connector
debug_flags = (union replay_debug_flags *)&pr_config.debug_flags;
debug_flags->u32All = 0;
- debug_flags->bitfields.visual_confirm =
- link->ctx->dc->debug.visual_confirm == VISUAL_CONFIRM_REPLAY;
+ debug_flags->bitfields.visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_REPLAY;
debug_flags->bitfields.skip_crtc_disabled = dc->debug.replay_skip_crtc_disabled;
init_replay_config(link, &pr_config);
@@ -144,7 +143,6 @@ bool amdgpu_dm_link_setup_replay(struct dc_stream_state *stream,
{
struct dc_link *link;
unsigned int static_coasting_vtotal;
- unsigned int nom_coasting_vtotal;
if (!stream || !stream->link || !vrr_params)
return false;
@@ -159,12 +157,11 @@ bool amdgpu_dm_link_setup_replay(struct dc_stream_state *stream,
calculate_replay_link_off_frame_count(link, stream->timing.v_total,
stream->timing.h_total);
- nom_coasting_vtotal = stream->timing.v_total;
static_coasting_vtotal = mod_freesync_calc_v_total_from_refresh(stream,
vrr_params->min_refresh_in_uhz);
set_replay_coasting_vtotal(link, PR_COASTING_TYPE_NOM,
- nom_coasting_vtotal);
+ stream->timing.v_total);
set_replay_coasting_vtotal(link, PR_COASTING_TYPE_STATIC,
static_coasting_vtotal);
return true;
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 09/24] drm/amd/display: Enable warnings as errors for KUnit tests
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (7 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 08/24] drm/amd/display: remove redundant code in amdgpu_dm_replay Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 10/24] drm/amd/display: Remove dead code in dm_dp_mst_get_modes Aurabindo Pillai
` (15 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Ray Wu
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Add CONFIG_WERROR=y to .kunitconfig to treat compiler warnings
as errors during KUnit builds, ensuring warnings are caught
early.
Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Ray Wu <ray.wu@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig
index bd1bf8d959f9..1e93bd8b44ce 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig
@@ -15,6 +15,9 @@ CONFIG_I2C=y
CONFIG_POWER_SUPPLY=y
CONFIG_CRC16=y
+# Treat warnings as errors
+CONFIG_WERROR=y
+
# GCOV Coverage - see tools/testing/kunit/configs/coverage_uml.config
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 10/24] drm/amd/display: Remove dead code in dm_dp_mst_get_modes
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (8 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 09/24] drm/amd/display: Enable warnings as errors for KUnit tests Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 11/24] drm/amd/display: Add KUnit tests for amdgpu_dm_mst_types Aurabindo Pillai
` (14 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Remove unreachable null check on aconnector after container_of,
and redundant dc_sink checks where dc_sink is guaranteed non-NULL
after earlier null-check with early return.
Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 23 ++++++++-----------
1 file changed, 9 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 8e2a8c2c1d84..3b6433fb1345 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -363,9 +363,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
int ret = 0;
- if (!aconnector)
- return drm_add_edid_modes(connector, NULL);
-
if (!aconnector->drm_edid) {
const struct drm_edid *drm_edid;
@@ -456,7 +453,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
* plugged back with same display index, its hdcp properties
* will be retrieved from hdcp_work within dm_dp_mst_get_modes
*/
- if (aconnector->dc_sink && connector->state) {
+ if (connector->state) {
struct drm_device *dev = connector->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
@@ -472,20 +469,18 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
}
}
- if (aconnector->dc_sink) {
- amdgpu_dm_update_freesync_caps(
- connector, aconnector->drm_edid, true);
+ amdgpu_dm_update_freesync_caps(
+ connector, aconnector->drm_edid, true);
#if defined(CONFIG_DRM_AMD_DC_FP)
- if (!validate_dsc_caps_on_connector(aconnector))
- memset(&aconnector->dc_sink->dsc_caps,
- 0, sizeof(aconnector->dc_sink->dsc_caps));
+ if (!validate_dsc_caps_on_connector(aconnector))
+ memset(&aconnector->dc_sink->dsc_caps,
+ 0, sizeof(aconnector->dc_sink->dsc_caps));
#endif
- if (!retrieve_downstream_port_device(aconnector))
- memset(&aconnector->mst_downstream_port_present,
- 0, sizeof(aconnector->mst_downstream_port_present));
- }
+ if (!retrieve_downstream_port_device(aconnector))
+ memset(&aconnector->mst_downstream_port_present,
+ 0, sizeof(aconnector->mst_downstream_port_present));
}
drm_edid_connector_update(&aconnector->base, aconnector->drm_edid);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 11/24] drm/amd/display: Add KUnit tests for amdgpu_dm_mst_types
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (9 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 10/24] drm/amd/display: Remove dead code in dm_dp_mst_get_modes Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 12/24] drm/amd/display: Fix incorrect logic in CRC source handling Aurabindo Pillai
` (13 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Add KUnit test coverage for needs_dsc_aux_workaround() in
amdgpu_dm_mst_types.c. Tests verify the function correctly
identifies links requiring the DSC AUX workaround based on
branch device ID, DPCD revision, and sink count.
Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +
.../display/amdgpu_dm/amdgpu_dm_mst_types.h | 6 +
.../drm/amd/display/amdgpu_dm/tests/Makefile | 1 +
.../tests/amdgpu_dm_mst_types_test.c | 124 ++++++++++++++++++
4 files changed, 133 insertions(+)
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 3b6433fb1345..9a70d1487b62 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -39,6 +39,7 @@
#include "dc.h"
#include "dm_helpers.h"
+#include "amdgpu_dm_kunit_helpers.h"
#include "ddc_service_types.h"
#include "dpcd_defs.h"
@@ -248,6 +249,7 @@ bool needs_dsc_aux_workaround(struct dc_link *link)
return false;
}
+EXPORT_IF_KUNIT(needs_dsc_aux_workaround);
#if defined(CONFIG_DRM_AMD_DC_FP)
static bool is_synaptics_cascaded_panamera(struct dc_link *link, struct drm_dp_mst_port *port)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index 6f7ea684b555..5a7065e53645 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -57,8 +57,14 @@ enum mst_msg_ready_type {
DOWN_OR_UP_MSG_RDY_EVENT = 3
};
+struct amdgpu_device;
struct amdgpu_display_manager;
struct amdgpu_dm_connector;
+struct dc_state;
+struct dc_stream_state;
+struct dm_atomic_state;
+struct drm_atomic_state;
+struct drm_dp_mst_topology_mgr;
uint32_t dm_mst_get_pbn_divider(struct dc_link *link);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
index ce1e46acb7af..fe9f32c9bdde 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_psr_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_replay_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_ism_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_wb_test.o
+obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_mst_types_test.o
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c
new file mode 100644
index 000000000000..e21386819ea1
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * KUnit tests for amdgpu_dm_mst_types.c
+ *
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#include <kunit/test.h>
+
+#include "dc.h"
+#include "dpcd_defs.h"
+#include "amdgpu_dm_mst_types.h"
+
+/* Tests for needs_dsc_aux_workaround */
+
+/**
+ * dm_mst_test_needs_dsc_aux_workaround_match - Test workaround triggers for matching device
+ * @test: KUnit test context
+ *
+ * Verify that needs_dsc_aux_workaround() returns true when the link has
+ * the specific branch device ID, DPCD rev 1.4, and sink count >= 2.
+ */
+static void dm_mst_test_needs_dsc_aux_workaround_match(struct kunit *test)
+{
+ struct dc_link link = {0};
+
+ link.dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_90CC24;
+ link.dpcd_caps.dpcd_rev.raw = DPCD_REV_14;
+ link.dpcd_caps.sink_count.bits.SINK_COUNT = 2;
+
+ KUNIT_EXPECT_TRUE(test, needs_dsc_aux_workaround(&link));
+}
+
+/**
+ * dm_mst_test_needs_dsc_aux_workaround_rev12 - Test workaround triggers for DPCD rev 1.2
+ * @test: KUnit test context
+ *
+ * Verify that needs_dsc_aux_workaround() returns true when the link has
+ * the specific branch device ID, DPCD rev 1.2, and sink count >= 2.
+ */
+static void dm_mst_test_needs_dsc_aux_workaround_rev12(struct kunit *test)
+{
+ struct dc_link link = {0};
+
+ link.dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_90CC24;
+ link.dpcd_caps.dpcd_rev.raw = DPCD_REV_12;
+ link.dpcd_caps.sink_count.bits.SINK_COUNT = 3;
+
+ KUNIT_EXPECT_TRUE(test, needs_dsc_aux_workaround(&link));
+}
+
+/**
+ * dm_mst_test_needs_dsc_aux_workaround_wrong_dev_id - Test workaround skipped for wrong device
+ * @test: KUnit test context
+ *
+ * Verify that needs_dsc_aux_workaround() returns false when the branch
+ * device ID does not match DP_BRANCH_DEVICE_ID_90CC24.
+ */
+static void dm_mst_test_needs_dsc_aux_workaround_wrong_dev_id(struct kunit *test)
+{
+ struct dc_link link = {0};
+
+ link.dpcd_caps.branch_dev_id = 0x123456;
+ link.dpcd_caps.dpcd_rev.raw = DPCD_REV_14;
+ link.dpcd_caps.sink_count.bits.SINK_COUNT = 2;
+
+ KUNIT_EXPECT_FALSE(test, needs_dsc_aux_workaround(&link));
+}
+
+/**
+ * dm_mst_test_needs_dsc_aux_workaround_wrong_rev - Test workaround skipped for unsupported rev
+ * @test: KUnit test context
+ *
+ * Verify that needs_dsc_aux_workaround() returns false when the DPCD
+ * revision is neither 1.2 nor 1.4.
+ */
+static void dm_mst_test_needs_dsc_aux_workaround_wrong_rev(struct kunit *test)
+{
+ struct dc_link link = {0};
+
+ link.dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_90CC24;
+ link.dpcd_caps.dpcd_rev.raw = 0x11; /* DPCD 1.1 */
+ link.dpcd_caps.sink_count.bits.SINK_COUNT = 2;
+
+ KUNIT_EXPECT_FALSE(test, needs_dsc_aux_workaround(&link));
+}
+
+/**
+ * dm_mst_test_needs_dsc_aux_workaround_low_sink_count - Test workaround skipped for single sink
+ * @test: KUnit test context
+ *
+ * Verify that needs_dsc_aux_workaround() returns false when the sink
+ * count is less than 2, even if device ID and DPCD rev match.
+ */
+static void dm_mst_test_needs_dsc_aux_workaround_low_sink_count(struct kunit *test)
+{
+ struct dc_link link = {0};
+
+ link.dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_90CC24;
+ link.dpcd_caps.dpcd_rev.raw = DPCD_REV_14;
+ link.dpcd_caps.sink_count.bits.SINK_COUNT = 1;
+
+ KUNIT_EXPECT_FALSE(test, needs_dsc_aux_workaround(&link));
+}
+
+static struct kunit_case dm_mst_types_test_cases[] = {
+ /* needs_dsc_aux_workaround tests */
+ KUNIT_CASE(dm_mst_test_needs_dsc_aux_workaround_match),
+ KUNIT_CASE(dm_mst_test_needs_dsc_aux_workaround_rev12),
+ KUNIT_CASE(dm_mst_test_needs_dsc_aux_workaround_wrong_dev_id),
+ KUNIT_CASE(dm_mst_test_needs_dsc_aux_workaround_wrong_rev),
+ KUNIT_CASE(dm_mst_test_needs_dsc_aux_workaround_low_sink_count),
+ {}
+};
+
+static struct kunit_suite dm_mst_types_test_suite = {
+ .name = "amdgpu_dm_mst_types",
+ .test_cases = dm_mst_types_test_cases,
+};
+
+kunit_test_suite(dm_mst_types_test_suite);
+
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_mst_types");
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 12/24] drm/amd/display: Fix incorrect logic in CRC source handling
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (10 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 11/24] drm/amd/display: Add KUnit tests for amdgpu_dm_mst_types Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 13/24] drm/amd/display: Extract DPRX CRC transition helpers for KUnit testing Aurabindo Pillai
` (12 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Fix three issues amdgpu_dm_crc.c:
- Use cur_crc_src instead of source when deciding whether to call
drm_dp_stop_crc() in the disable path of set_crc_source(). When
disabling CRC, source is always NONE so dm_is_crc_source_dprx(source)
was always false, meaning drm_dp_stop_crc() was never called when
stopping a DPRX CRC source. Use cur_crc_src to check what was
previously active instead.
- Replace fragile 'source < 0' comparisons in verify_crc_source() and
set_crc_source() with AMDGPU_DM_PIPE_CRC_SOURCE_INVALID.
and avoiding signed/unsigned enum comparison concerns.
- Remove redundant NULL initializations for drm_dev and acrtc in
handle_crc_irq(). Both variables are unconditionally assigned right
after.
Assisted-by: Copilot:Claude-Sonnet-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index 3613e67d1085..d6d38c97fbad 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -496,7 +496,7 @@ amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
{
enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name);
- if (source < 0) {
+ if (source == AMDGPU_DM_PIPE_CRC_SOURCE_INVALID) {
DRM_DEBUG_DRIVER("Unknown CRC source %s for CRTC%d\n",
src_name, crtc->index);
return -EINVAL;
@@ -595,7 +595,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
bool enabled = false;
int ret = 0;
- if (source < 0) {
+ if (source == AMDGPU_DM_PIPE_CRC_SOURCE_INVALID) {
DRM_DEBUG_DRIVER("Unknown CRC source %s for CRTC%d\n",
src_name, crtc->index);
return -EINVAL;
@@ -724,7 +724,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
}
} else if (enabled && !enable) {
drm_crtc_vblank_put(crtc);
- if (dm_is_crc_source_dprx(source)) {
+ if (dm_is_crc_source_dprx(cur_crc_src)) {
if (drm_dp_stop_crc(aux)) {
DRM_DEBUG_DRIVER("dp stop crc failed\n");
ret = -EINVAL;
@@ -767,9 +767,9 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc)
{
struct dm_crtc_state *crtc_state;
struct dc_stream_state *stream_state;
- struct drm_device *drm_dev = NULL;
+ struct drm_device *drm_dev;
enum amdgpu_dm_pipe_crc_source cur_crc_src;
- struct amdgpu_crtc *acrtc = NULL;
+ struct amdgpu_crtc *acrtc;
uint32_t crcs[3];
unsigned long flags;
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 13/24] drm/amd/display: Extract DPRX CRC transition helpers for KUnit testing
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (11 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 12/24] drm/amd/display: Fix incorrect logic in CRC source handling Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 14/24] drm/amd/display: Extract HDCP testable helpers for KUnit Aurabindo Pillai
` (11 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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
From: Alex Hung <alex.hung@amd.com>
Extract three pure predicate functions from amdgpu_dm_crtc_set_crc_source():
- dm_need_dp_aux
- dm_crc_source_should_start_dprx
- dm_crc_source_should_stop_dprx
Refactor set_crc_source() to use these helpers, replacing the nested
if/else if structure with flat, mutually-exclusive branches driven by
the new predicates.
Add KUnit test cases covering all relevant source combinations for each
helper, including the regression case where DPRX→NONE must trigger
drm_dp_stop_crc().
Assisted-by: Copilot:Claude-Sonnet-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 92 ++++++++++---
.../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 6 +
.../amdgpu_dm/tests/amdgpu_dm_crc_test.c | 122 ++++++++++++++++++
3 files changed, 203 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index d6d38c97fbad..7b0604e9216a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -87,6 +87,65 @@ bool dm_need_crc_dither(enum amdgpu_dm_pipe_crc_source src)
}
EXPORT_IF_KUNIT(dm_need_crc_dither);
+/**
+ * dm_need_dp_aux() - Does this source transition require the DP AUX handle?
+ * @source: Requested CRC source.
+ * @cur_crc_src: Current CRC source.
+ *
+ * Returns true when either the new source is DPRX-based (starting DPRX CRC),
+ * or the current source is DPRX-based and the new source is NONE (stopping it).
+ *
+ * Return: true if the DP AUX handle is needed, false otherwise.
+ */
+STATIC_IFN_KUNIT
+bool dm_need_dp_aux(enum amdgpu_dm_pipe_crc_source source,
+ enum amdgpu_dm_pipe_crc_source cur_crc_src)
+{
+ return dm_is_crc_source_dprx(source) ||
+ (source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE && dm_is_crc_source_dprx(cur_crc_src));
+}
+EXPORT_IF_KUNIT(dm_need_dp_aux);
+
+/**
+ * dm_crc_source_should_start_dprx() - Should drm_dp_start_crc() be called?
+ * @source: Requested CRC source.
+ * @cur_crc_src: Current CRC source.
+ *
+ * True when CRC is transitioning from off to a DPRX source
+ * (!enabled && enable && is_dprx(@source)).
+ *
+ * Return: true if drm_dp_start_crc() should be called, false otherwise.
+ */
+STATIC_IFN_KUNIT
+bool dm_crc_source_should_start_dprx(enum amdgpu_dm_pipe_crc_source source,
+ enum amdgpu_dm_pipe_crc_source cur_crc_src)
+{
+ return !amdgpu_dm_is_valid_crc_source(cur_crc_src) &&
+ amdgpu_dm_is_valid_crc_source(source) &&
+ dm_is_crc_source_dprx(source);
+}
+EXPORT_IF_KUNIT(dm_crc_source_should_start_dprx);
+
+/**
+ * dm_crc_source_should_stop_dprx() - Should drm_dp_stop_crc() be called?
+ * @source: Requested CRC source.
+ * @cur_crc_src: Current CRC source.
+ *
+ * True when CRC is transitioning from a DPRX source to off
+ * (enabled && !enable && is_dprx(@cur_crc_src)).
+ *
+ * Return: true if drm_dp_stop_crc() should be called, false otherwise.
+ */
+STATIC_IFN_KUNIT
+bool dm_crc_source_should_stop_dprx(enum amdgpu_dm_pipe_crc_source source,
+ enum amdgpu_dm_pipe_crc_source cur_crc_src)
+{
+ return amdgpu_dm_is_valid_crc_source(cur_crc_src) &&
+ !amdgpu_dm_is_valid_crc_source(source) &&
+ dm_is_crc_source_dprx(cur_crc_src);
+}
+EXPORT_IF_KUNIT(dm_crc_source_should_stop_dprx);
+
const char *const *amdgpu_dm_crtc_get_crc_sources(struct drm_crtc *crtc,
size_t *count)
{
@@ -650,9 +709,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
* CRTC DITHER | XXXX | Enable CRTC CRC, set dither
* DPRX DITHER | XXXX | Enable DPRX CRC, need 'aux', set dither
*/
- if (dm_is_crc_source_dprx(source) ||
- (source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE &&
- dm_is_crc_source_dprx(cur_crc_src))) {
+ if (dm_need_dp_aux(source, cur_crc_src)) {
struct amdgpu_dm_connector *aconn = NULL;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
@@ -714,23 +771,24 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
goto cleanup;
}
- if (!enabled && enable) {
- if (dm_is_crc_source_dprx(source)) {
- if (drm_dp_start_crc(aux, crtc)) {
- DRM_DEBUG_DRIVER("dp start crc failed\n");
- ret = -EINVAL;
- goto cleanup;
- }
+ if (dm_crc_source_should_start_dprx(source, cur_crc_src)) {
+ /* !enabled && enable && is_dprx(source): CRC off → DPRX on */
+ if (drm_dp_start_crc(aux, crtc)) {
+ DRM_DEBUG_DRIVER("dp start crc failed\n");
+ ret = -EINVAL;
+ goto cleanup;
}
- } else if (enabled && !enable) {
+ } else if (dm_crc_source_should_stop_dprx(source, cur_crc_src)) {
+ /* enabled && !enable && is_dprx(cur_crc_src): DPRX on → CRC off */
drm_crtc_vblank_put(crtc);
- if (dm_is_crc_source_dprx(cur_crc_src)) {
- if (drm_dp_stop_crc(aux)) {
- DRM_DEBUG_DRIVER("dp stop crc failed\n");
- ret = -EINVAL;
- goto cleanup;
- }
+ if (drm_dp_stop_crc(aux)) {
+ DRM_DEBUG_DRIVER("dp stop crc failed\n");
+ ret = -EINVAL;
+ goto cleanup;
}
+ } else if (enabled && !enable) {
+ /* Non-DPRX source (e.g. CRTC) turning off: release vblank ref */
+ drm_crtc_vblank_put(crtc);
}
spin_lock_irq(&drm_dev->event_lock);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
index c9aa0c82038f..8bb8a6f6c148 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
@@ -156,6 +156,12 @@ enum amdgpu_dm_pipe_crc_source dm_parse_crc_source(const char *source);
bool dm_is_crc_source_crtc(enum amdgpu_dm_pipe_crc_source src);
bool dm_is_crc_source_dprx(enum amdgpu_dm_pipe_crc_source src);
bool dm_need_crc_dither(enum amdgpu_dm_pipe_crc_source src);
+bool dm_need_dp_aux(enum amdgpu_dm_pipe_crc_source source,
+ enum amdgpu_dm_pipe_crc_source cur_crc_src);
+bool dm_crc_source_should_start_dprx(enum amdgpu_dm_pipe_crc_source source,
+ enum amdgpu_dm_pipe_crc_source cur_crc_src);
+bool dm_crc_source_should_stop_dprx(enum amdgpu_dm_pipe_crc_source source,
+ enum amdgpu_dm_pipe_crc_source cur_crc_src);
#endif
#endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
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 bba8b1a8fa1c..a6fd3a6fd803 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
@@ -95,17 +95,139 @@ static void dm_test_is_valid_crc_source(struct kunit *test)
KUNIT_EXPECT_FALSE(test, amdgpu_dm_is_valid_crc_source(AMDGPU_DM_PIPE_CRC_SOURCE_INVALID));
}
+/**
+ * dm_test_need_dp_aux() - Test dm_need_dp_aux().
+ * @test: KUnit test context.
+ *
+ * Verifies that dm_need_dp_aux() returns true when the transition starts or
+ * stops a DPRX CRC source (requiring the DP AUX handle), and false for
+ * non-DPRX transitions such as CRTC or NONE→NONE.
+ */
+static void dm_test_need_dp_aux(struct kunit *test)
+{
+ /* Starting a DPRX source always needs AUX, regardless of current source */
+ KUNIT_EXPECT_TRUE(test, dm_need_dp_aux(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+ KUNIT_EXPECT_TRUE(test, dm_need_dp_aux(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
+ AMDGPU_DM_PIPE_CRC_SOURCE_CRTC));
+ KUNIT_EXPECT_TRUE(test, dm_need_dp_aux(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+
+ /* Stopping a DPRX source (NONE requested, DPRX was active) needs AUX */
+ KUNIT_EXPECT_TRUE(test, dm_need_dp_aux(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+ KUNIT_EXPECT_TRUE(test, dm_need_dp_aux(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER));
+
+ /* CRTC transitions do not need AUX */
+ KUNIT_EXPECT_FALSE(test, dm_need_dp_aux(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+ KUNIT_EXPECT_FALSE(test, dm_need_dp_aux(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_CRTC));
+ KUNIT_EXPECT_FALSE(test, dm_need_dp_aux(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+}
+
+/**
+ * dm_test_crc_source_should_start_dprx() - Test dm_crc_source_should_start_dprx().
+ * @test: KUnit test context.
+ *
+ * Verifies that dm_crc_source_should_start_dprx() returns true only when CRC
+ * is transitioning from off (!enabled) to a DPRX source (enable &&
+ * is_dprx(source)), and false for all other combinations including
+ * already-enabled or non-DPRX targets.
+ */
+static void dm_test_crc_source_should_start_dprx(struct kunit *test)
+{
+ /* CRC off → DPRX: should start */
+ KUNIT_EXPECT_TRUE(test,
+ dm_crc_source_should_start_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+ KUNIT_EXPECT_TRUE(test,
+ dm_crc_source_should_start_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+
+ /* CRC already on (any source) → DPRX: should NOT start (already enabled) */
+ KUNIT_EXPECT_FALSE(test,
+ dm_crc_source_should_start_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
+ AMDGPU_DM_PIPE_CRC_SOURCE_CRTC));
+ KUNIT_EXPECT_FALSE(test,
+ dm_crc_source_should_start_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
+ AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+
+ /* CRC off → CRTC: not a DPRX start */
+ KUNIT_EXPECT_FALSE(test,
+ dm_crc_source_should_start_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+
+ /* Disabling: should not start */
+ KUNIT_EXPECT_FALSE(test,
+ dm_crc_source_should_start_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+}
+
+/**
+ * dm_test_crc_source_should_stop_dprx() - Test dm_crc_source_should_stop_dprx().
+ * @test: KUnit test context.
+ *
+ * Verifies that dm_crc_source_should_stop_dprx() returns true only when CRC
+ * is transitioning from a DPRX source (enabled && is_dprx(cur_crc_src)) to
+ * off (!enable), and false for non-DPRX disables, DPRX starts, and no-op
+ * transitions.
+ */
+static void dm_test_crc_source_should_stop_dprx(struct kunit *test)
+{
+ /* DPRX → off: should stop */
+ KUNIT_EXPECT_TRUE(test,
+ dm_crc_source_should_stop_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+ KUNIT_EXPECT_TRUE(test,
+ dm_crc_source_should_stop_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER));
+
+ /* CRTC → off: not a DPRX stop */
+ KUNIT_EXPECT_FALSE(test,
+ dm_crc_source_should_stop_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_CRTC));
+
+ /* off → DPRX: not a stop */
+ KUNIT_EXPECT_FALSE(test,
+ dm_crc_source_should_stop_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+
+ /* DPRX → DPRX: no transition, not a stop */
+ KUNIT_EXPECT_FALSE(test,
+ dm_crc_source_should_stop_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
+ AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+
+ /* off → off: not a stop */
+ KUNIT_EXPECT_FALSE(test,
+ dm_crc_source_should_stop_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_NONE,
+ AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+}
+
static struct kunit_case dm_crc_test_cases[] = {
+ /* dm_parse_crc_source() */
KUNIT_CASE(dm_test_parse_crc_source_none),
KUNIT_CASE(dm_test_parse_crc_source_crtc),
KUNIT_CASE(dm_test_parse_crc_source_dprx),
KUNIT_CASE(dm_test_parse_crc_source_crtc_dither),
KUNIT_CASE(dm_test_parse_crc_source_dprx_dither),
KUNIT_CASE(dm_test_parse_crc_source_invalid),
+ /* dm_is_crc_source_crtc() */
KUNIT_CASE(dm_test_is_crc_source_crtc),
+ /* dm_is_crc_source_dprx() */
KUNIT_CASE(dm_test_is_crc_source_dprx),
+ /* dm_need_crc_dither() */
KUNIT_CASE(dm_test_need_crc_dither),
+ /* amdgpu_dm_is_valid_crc_source() */
KUNIT_CASE(dm_test_is_valid_crc_source),
+ /* dm_need_dp_aux() */
+ KUNIT_CASE(dm_test_need_dp_aux),
+ /* dm_crc_source_should_start_dprx() */
+ KUNIT_CASE(dm_test_crc_source_should_start_dprx),
+ /* dm_crc_source_should_stop_dprx() */
+ KUNIT_CASE(dm_test_crc_source_should_stop_dprx),
{}
};
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 14/24] drm/amd/display: Extract HDCP testable helpers for KUnit
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (12 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 13/24] drm/amd/display: Extract DPRX CRC transition helpers for KUnit testing Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 15/24] drm/amd/display: Restore periodic detection for DCN35 Aurabindo Pillai
` (10 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Extract hdcp_get_content_protection_from_status() and
hdcp_get_link_display_adjustments() from event_property_update()
and hdcp_update_display() so the pure decision logic can be
KUnit-tested.
Also update function comments to kernel-doc formats.
Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 115 ++++---
.../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 12 +
.../amdgpu_dm/tests/amdgpu_dm_hdcp_test.c | 297 +++++++++++++++++-
3 files changed, 370 insertions(+), 54 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
index d1de295f1171..039f6516085c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
@@ -182,6 +182,70 @@ void process_output(struct hdcp_workqueue *hdcp_work)
}
EXPORT_IF_KUNIT(process_output);
+STATIC_IFN_KUNIT
+bool hdcp_get_content_protection_from_status(
+ unsigned int hdcp_content_type,
+ enum mod_hdcp_encryption_status encryption_status,
+ unsigned int *content_protection)
+{
+ if (encryption_status == MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF) {
+ *content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ return true;
+ }
+
+ if (hdcp_content_type == DRM_MODE_HDCP_CONTENT_TYPE0 &&
+ encryption_status <= MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON) {
+ *content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ return true;
+ }
+
+ if (hdcp_content_type == DRM_MODE_HDCP_CONTENT_TYPE1 &&
+ encryption_status == MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON) {
+ *content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+ return true;
+ }
+
+ return false;
+}
+EXPORT_IF_KUNIT(hdcp_get_content_protection_from_status);
+
+STATIC_IFN_KUNIT
+void hdcp_get_link_display_adjustments(
+ bool enable_encryption,
+ u8 content_type,
+ bool fused_io_supported,
+ bool hdcp_lc_force_fw_enable,
+ bool hdcp_lc_enable_sw_fallback,
+ struct mod_hdcp_link_adjustment *link_adjust,
+ struct mod_hdcp_display_adjustment *display_adjust)
+{
+ memset(link_adjust, 0, sizeof(*link_adjust));
+ memset(display_adjust, 0, sizeof(*display_adjust));
+
+ if (!enable_encryption) {
+ display_adjust->disable =
+ MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
+ return;
+ }
+
+ display_adjust->disable = MOD_HDCP_DISPLAY_NOT_DISABLE;
+ link_adjust->auth_delay = 2;
+ link_adjust->retry_limit = MAX_NUM_OF_ATTEMPTS;
+
+ if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) {
+ link_adjust->hdcp2.force_type = MOD_HDCP_FORCE_TYPE_0;
+ } else if (content_type == DRM_MODE_HDCP_CONTENT_TYPE1) {
+ link_adjust->hdcp1.disable = 1;
+ link_adjust->hdcp2.force_type = MOD_HDCP_FORCE_TYPE_1;
+ }
+
+ link_adjust->hdcp2.use_fw_locality_check =
+ fused_io_supported || hdcp_lc_force_fw_enable;
+ link_adjust->hdcp2.use_sw_locality_fallback =
+ hdcp_lc_enable_sw_fallback;
+}
+EXPORT_IF_KUNIT(hdcp_get_link_display_adjustments);
+
static void link_lock(struct hdcp_workqueue *work, bool lock)
{
int i = 0;
@@ -212,8 +276,11 @@ void hdcp_update_display(struct hdcp_workqueue *hdcp_work,
drm_connector_put(&hdcp_w->aconnector[conn_index]->base);
hdcp_w->aconnector[conn_index] = aconnector;
- memset(&link_adjust, 0, sizeof(link_adjust));
- memset(&display_adjust, 0, sizeof(display_adjust));
+ hdcp_get_link_display_adjustments(enable_encryption, content_type,
+ dc->caps.fused_io_supported,
+ dc->debug.hdcp_lc_force_fw_enable,
+ dc->debug.hdcp_lc_enable_sw_fallback,
+ &link_adjust, &display_adjust);
if (enable_encryption) {
/* Explicitly set the saved SRM as sysfs call will be after we already enabled hdcp
@@ -224,25 +291,9 @@ void hdcp_update_display(struct hdcp_workqueue *hdcp_work,
hdcp_work->srm_size,
&hdcp_work->srm_version);
- display_adjust.disable = MOD_HDCP_DISPLAY_NOT_DISABLE;
-
- link_adjust.auth_delay = 2;
- link_adjust.retry_limit = MAX_NUM_OF_ATTEMPTS;
-
- if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) {
- link_adjust.hdcp2.force_type = MOD_HDCP_FORCE_TYPE_0;
- } else if (content_type == DRM_MODE_HDCP_CONTENT_TYPE1) {
- link_adjust.hdcp1.disable = 1;
- link_adjust.hdcp2.force_type = MOD_HDCP_FORCE_TYPE_1;
- }
- link_adjust.hdcp2.use_fw_locality_check =
- (dc->caps.fused_io_supported || dc->debug.hdcp_lc_force_fw_enable);
- link_adjust.hdcp2.use_sw_locality_fallback = dc->debug.hdcp_lc_enable_sw_fallback;
-
schedule_delayed_work(&hdcp_w->property_validate_dwork,
msecs_to_jiffies(DRM_HDCP_CHECK_PERIOD_MS));
} else {
- display_adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
hdcp_w->encryption_status[conn_index] = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
cancel_delayed_work(&hdcp_w->property_validate_dwork);
}
@@ -336,6 +387,7 @@ static void event_property_update(struct work_struct *work)
property_update_work);
struct amdgpu_dm_connector *aconnector = NULL;
struct drm_device *dev;
+ unsigned int content_protection;
long ret;
unsigned int conn_index;
struct drm_connector *connector;
@@ -375,26 +427,15 @@ static void event_property_update(struct work_struct *work)
MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
}
}
- if (hdcp_work->encryption_status[conn_index] !=
- MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF) {
- if (conn_state->hdcp_content_type ==
- DRM_MODE_HDCP_CONTENT_TYPE0 &&
- hdcp_work->encryption_status[conn_index] <=
- MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON) {
+ if (hdcp_get_content_protection_from_status(conn_state->hdcp_content_type,
+ hdcp_work->encryption_status[conn_index],
+ &content_protection)) {
+ if (content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
DRM_DEBUG_DRIVER("[HDCP_DM] DRM_MODE_CONTENT_PROTECTION_ENABLED\n");
- drm_hdcp_update_content_protection(connector,
- DRM_MODE_CONTENT_PROTECTION_ENABLED);
- } else if (conn_state->hdcp_content_type ==
- DRM_MODE_HDCP_CONTENT_TYPE1 &&
- hdcp_work->encryption_status[conn_index] ==
- MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON) {
- drm_hdcp_update_content_protection(connector,
- DRM_MODE_CONTENT_PROTECTION_ENABLED);
- }
- } else {
- DRM_DEBUG_DRIVER("[HDCP_DM] DRM_MODE_CONTENT_PROTECTION_DESIRED\n");
- drm_hdcp_update_content_protection(connector,
- DRM_MODE_CONTENT_PROTECTION_DESIRED);
+ else
+ DRM_DEBUG_DRIVER("[HDCP_DM] DRM_MODE_CONTENT_PROTECTION_DESIRED\n");
+
+ drm_hdcp_update_content_protection(connector, content_protection);
}
drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
index 90b18c450ca6..3ba5823aed9f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
@@ -96,6 +96,18 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
void process_output(struct hdcp_workqueue *hdcp_work);
+bool hdcp_get_content_protection_from_status(
+ unsigned int hdcp_content_type,
+ enum mod_hdcp_encryption_status encryption_status,
+ unsigned int *content_protection);
+void hdcp_get_link_display_adjustments(
+ bool enable_encryption,
+ u8 content_type,
+ bool fused_io_supported,
+ bool hdcp_lc_force_fw_enable,
+ bool hdcp_lc_enable_sw_fallback,
+ struct mod_hdcp_link_adjustment *link_adjust,
+ struct mod_hdcp_display_adjustment *display_adjust);
#endif
#endif /* AMDGPU_DM_AMDGPU_DM_HDCP_H_ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c
index d03b606d27bc..619b4a80c82b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c
@@ -12,11 +12,241 @@
static void dummy_work_fn(struct work_struct *work) {}
+/* Tests for hdcp_get_content_protection_from_status() */
+
+/**
+ * dm_test_hdcp_get_cp_disabled_returns_desired - HDCP off maps to DESIRED
+ * @test: KUnit test context
+ *
+ * When encryption status is HDCP_OFF, content_protection should be set
+ * to DESIRED and the function should return true to indicate an update.
+ */
+static void dm_test_hdcp_get_cp_disabled_returns_desired(struct kunit *test)
+{
+ unsigned int content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ bool update;
+
+ update = hdcp_get_content_protection_from_status(
+ DRM_MODE_HDCP_CONTENT_TYPE0,
+ MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF,
+ &content_protection);
+
+ KUNIT_EXPECT_TRUE(test, update);
+ KUNIT_EXPECT_EQ(test, content_protection,
+ DRM_MODE_CONTENT_PROTECTION_DESIRED);
+}
+
+/**
+ * dm_test_hdcp_get_cp_type0_returns_enabled - TYPE0 with TYPE0_ON maps to ENABLED
+ * @test: KUnit test context
+ *
+ * When content type is TYPE0 and encryption status is at or below
+ * HDCP2_TYPE0_ON, content_protection should be set to ENABLED.
+ */
+static void dm_test_hdcp_get_cp_type0_returns_enabled(struct kunit *test)
+{
+ unsigned int content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ bool update;
+
+ update = hdcp_get_content_protection_from_status(
+ DRM_MODE_HDCP_CONTENT_TYPE0,
+ MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON,
+ &content_protection);
+
+ KUNIT_EXPECT_TRUE(test, update);
+ KUNIT_EXPECT_EQ(test, content_protection,
+ DRM_MODE_CONTENT_PROTECTION_ENABLED);
+}
+
+/**
+ * dm_test_hdcp_get_cp_type1_returns_enabled - TYPE1 with TYPE1_ON maps to ENABLED
+ * @test: KUnit test context
+ *
+ * When content type is TYPE1 and encryption status is exactly
+ * HDCP2_TYPE1_ON, content_protection should be set to ENABLED.
+ */
+static void dm_test_hdcp_get_cp_type1_returns_enabled(struct kunit *test)
+{
+ unsigned int content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ bool update;
+
+ update = hdcp_get_content_protection_from_status(
+ DRM_MODE_HDCP_CONTENT_TYPE1,
+ MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON,
+ &content_protection);
+
+ KUNIT_EXPECT_TRUE(test, update);
+ KUNIT_EXPECT_EQ(test, content_protection,
+ DRM_MODE_CONTENT_PROTECTION_ENABLED);
+}
+
+/**
+ * dm_test_hdcp_get_cp_type1_rejects_type0_status - TYPE1 rejects TYPE0_ON
+ * @test: KUnit test context
+ *
+ * When content type is TYPE1 but encryption status is only TYPE0_ON,
+ * the function should return false and leave content_protection unchanged.
+ */
+static void dm_test_hdcp_get_cp_type1_rejects_type0_status(struct kunit *test)
+{
+ unsigned int content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ bool update;
+
+ update = hdcp_get_content_protection_from_status(
+ DRM_MODE_HDCP_CONTENT_TYPE1,
+ MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON,
+ &content_protection);
+
+ KUNIT_EXPECT_FALSE(test, update);
+ KUNIT_EXPECT_EQ(test, content_protection,
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
+}
+
+/**
+ * dm_test_hdcp_get_cp_type0_rejects_type1_status - TYPE0 rejects TYPE1_ON
+ * @test: KUnit test context
+ *
+ * When content type is TYPE0 but encryption status exceeds the TYPE0_ON
+ * boundary (TYPE1_ON), the function should return false.
+ */
+static void dm_test_hdcp_get_cp_type0_rejects_type1_status(struct kunit *test)
+{
+ unsigned int content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+ bool update;
+
+ update = hdcp_get_content_protection_from_status(
+ DRM_MODE_HDCP_CONTENT_TYPE0,
+ MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON,
+ &content_protection);
+
+ KUNIT_EXPECT_FALSE(test, update);
+ KUNIT_EXPECT_EQ(test, content_protection,
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
+}
+
+/* Tests for hdcp_get_link_display_adjustments() */
+
+/**
+ * dm_test_hdcp_get_adjustments_disable_authentication - disable path zeroes adjustments
+ * @test: KUnit test context
+ *
+ * When enable_encryption is false, display_adjust should disable
+ * authentication and all link_adjust fields should remain zeroed.
+ */
+static void dm_test_hdcp_get_adjustments_disable_authentication(struct kunit *test)
+{
+ struct mod_hdcp_link_adjustment link_adjust;
+ struct mod_hdcp_display_adjustment display_adjust;
+ unsigned int disable;
+ unsigned int hdcp1_disable;
+ unsigned int force_type;
+
+ hdcp_get_link_display_adjustments(false, DRM_MODE_HDCP_CONTENT_TYPE0,
+ false, false, false, &link_adjust, &display_adjust);
+ disable = display_adjust.disable;
+ hdcp1_disable = link_adjust.hdcp1.disable;
+ force_type = link_adjust.hdcp2.force_type;
+
+ KUNIT_EXPECT_EQ(test, disable,
+ MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION);
+ KUNIT_EXPECT_EQ(test, link_adjust.auth_delay, 0);
+ KUNIT_EXPECT_EQ(test, link_adjust.retry_limit, 0);
+ KUNIT_EXPECT_EQ(test, hdcp1_disable, 0);
+ KUNIT_EXPECT_EQ(test, force_type, 0);
+}
+
+/**
+ * dm_test_hdcp_get_adjustments_type0_policy - TYPE0 enables HDCP1 and forces TYPE0
+ * @test: KUnit test context
+ *
+ * When encryption is enabled with content TYPE0, hdcp1 should remain
+ * enabled, force_type should be TYPE_0, and sw_locality_fallback should
+ * be propagated from the input parameter.
+ */
+static void dm_test_hdcp_get_adjustments_type0_policy(struct kunit *test)
+{
+ struct mod_hdcp_link_adjustment link_adjust;
+ struct mod_hdcp_display_adjustment display_adjust;
+ unsigned int disable;
+ unsigned int hdcp1_disable;
+ unsigned int force_type;
+
+ hdcp_get_link_display_adjustments(true, DRM_MODE_HDCP_CONTENT_TYPE0,
+ false, false, true, &link_adjust, &display_adjust);
+ disable = display_adjust.disable;
+ hdcp1_disable = link_adjust.hdcp1.disable;
+ force_type = link_adjust.hdcp2.force_type;
+
+ KUNIT_EXPECT_EQ(test, disable,
+ MOD_HDCP_DISPLAY_NOT_DISABLE);
+ KUNIT_EXPECT_EQ(test, link_adjust.auth_delay, 2);
+ KUNIT_EXPECT_EQ(test, link_adjust.retry_limit, MAX_NUM_OF_ATTEMPTS);
+ KUNIT_EXPECT_EQ(test, hdcp1_disable, 0);
+ KUNIT_EXPECT_EQ(test, force_type,
+ MOD_HDCP_FORCE_TYPE_0);
+ KUNIT_EXPECT_FALSE(test, link_adjust.hdcp2.use_fw_locality_check);
+ KUNIT_EXPECT_TRUE(test, link_adjust.hdcp2.use_sw_locality_fallback);
+}
+
+/**
+ * dm_test_hdcp_get_adjustments_type1_policy - TYPE1 disables HDCP1 and forces TYPE1
+ * @test: KUnit test context
+ *
+ * When encryption is enabled with content TYPE1, hdcp1 should be
+ * disabled, force_type should be TYPE_1, and fw_locality_check should
+ * be enabled when hdcp_lc_force_fw_enable is set.
+ */
+static void dm_test_hdcp_get_adjustments_type1_policy(struct kunit *test)
+{
+ struct mod_hdcp_link_adjustment link_adjust;
+ struct mod_hdcp_display_adjustment display_adjust;
+ unsigned int disable;
+ unsigned int hdcp1_disable;
+ unsigned int force_type;
+
+ hdcp_get_link_display_adjustments(true, DRM_MODE_HDCP_CONTENT_TYPE1,
+ false, true, false, &link_adjust, &display_adjust);
+ disable = display_adjust.disable;
+ hdcp1_disable = link_adjust.hdcp1.disable;
+ force_type = link_adjust.hdcp2.force_type;
+
+ KUNIT_EXPECT_EQ(test, disable,
+ MOD_HDCP_DISPLAY_NOT_DISABLE);
+ KUNIT_EXPECT_EQ(test, link_adjust.auth_delay, 2);
+ KUNIT_EXPECT_EQ(test, link_adjust.retry_limit, MAX_NUM_OF_ATTEMPTS);
+ KUNIT_EXPECT_EQ(test, hdcp1_disable, 1);
+ KUNIT_EXPECT_EQ(test, force_type,
+ MOD_HDCP_FORCE_TYPE_1);
+ KUNIT_EXPECT_TRUE(test, link_adjust.hdcp2.use_fw_locality_check);
+ KUNIT_EXPECT_FALSE(test, link_adjust.hdcp2.use_sw_locality_fallback);
+}
+
+/**
+ * dm_test_hdcp_get_adjustments_fused_io_enables_fw_check - fused_io enables FW locality check
+ * @test: KUnit test context
+ *
+ * When fused_io_supported is true, use_fw_locality_check should be
+ * enabled regardless of hdcp_lc_force_fw_enable.
+ */
+static void dm_test_hdcp_get_adjustments_fused_io_enables_fw_check(struct kunit *test)
+{
+ struct mod_hdcp_link_adjustment link_adjust;
+ struct mod_hdcp_display_adjustment display_adjust;
+
+ hdcp_get_link_display_adjustments(true, DRM_MODE_HDCP_CONTENT_TYPE0,
+ true, false, false, &link_adjust, &display_adjust);
+
+ KUNIT_EXPECT_TRUE(test, link_adjust.hdcp2.use_fw_locality_check);
+}
+
/* Tests for process_output() */
-/*
- * Helper: allocate and initialise a minimal hdcp_workqueue sufficient for
- * process_output() testing. Only the three delayed works accessed by
+/**
+ * alloc_test_workqueue - allocate a minimal hdcp_workqueue for testing
+ * @test: KUnit test context for managed allocation
+ *
+ * Allocates and initialises a minimal hdcp_workqueue sufficient for
+ * process_output() testing. Only the three delayed works accessed by
* process_output() are initialised; everything else is zeroed.
*/
static struct hdcp_workqueue *alloc_test_workqueue(struct kunit *test)
@@ -33,9 +263,12 @@ static struct hdcp_workqueue *alloc_test_workqueue(struct kunit *test)
return work;
}
-/*
+/**
+ * dm_test_process_output_property_validate_always_scheduled - validate_dwork always queued
+ * @test: KUnit test context
+ *
* process_output() always schedules property_validate_dwork with delay=0,
- * which queues the work item directly (bypassing the timer). Use
+ * which queues the work item directly (bypassing the timer). Uses
* work_pending() rather than delayed_work_pending() to detect this.
*/
static void dm_test_process_output_property_validate_always_scheduled(struct kunit *test)
@@ -52,8 +285,12 @@ static void dm_test_process_output_property_validate_always_scheduled(struct kun
cancel_delayed_work_sync(&work->property_validate_dwork);
}
-/*
- * output.callback_needed=true must schedule callback_dwork.
+/**
+ * dm_test_process_output_callback_needed - callback_needed schedules callback_dwork
+ * @test: KUnit test context
+ *
+ * When output.callback_needed is true, process_output() must schedule
+ * callback_dwork with the specified delay.
*/
static void dm_test_process_output_callback_needed(struct kunit *test)
{
@@ -70,8 +307,12 @@ static void dm_test_process_output_callback_needed(struct kunit *test)
cancel_delayed_work_sync(&work->property_validate_dwork);
}
-/*
- * output.callback_stop=true must cancel a previously scheduled callback_dwork.
+/**
+ * dm_test_process_output_callback_stop - callback_stop cancels callback_dwork
+ * @test: KUnit test context
+ *
+ * When output.callback_stop is true, process_output() must cancel a
+ * previously scheduled callback_dwork.
*/
static void dm_test_process_output_callback_stop(struct kunit *test)
{
@@ -90,8 +331,12 @@ static void dm_test_process_output_callback_stop(struct kunit *test)
cancel_delayed_work_sync(&work->property_validate_dwork);
}
-/*
- * output.watchdog_timer_needed=true must schedule watchdog_timer_dwork.
+/**
+ * dm_test_process_output_watchdog_needed - watchdog_needed schedules watchdog_dwork
+ * @test: KUnit test context
+ *
+ * When output.watchdog_timer_needed is true, process_output() must
+ * schedule watchdog_timer_dwork with the specified delay.
*/
static void dm_test_process_output_watchdog_needed(struct kunit *test)
{
@@ -108,9 +353,12 @@ static void dm_test_process_output_watchdog_needed(struct kunit *test)
cancel_delayed_work_sync(&work->property_validate_dwork);
}
-/*
- * output.watchdog_timer_stop=true must cancel a previously scheduled
- * watchdog_timer_dwork.
+/**
+ * dm_test_process_output_watchdog_stop - watchdog_stop cancels watchdog_dwork
+ * @test: KUnit test context
+ *
+ * When output.watchdog_timer_stop is true, process_output() must cancel
+ * a previously scheduled watchdog_timer_dwork.
*/
static void dm_test_process_output_watchdog_stop(struct kunit *test)
{
@@ -129,9 +377,12 @@ static void dm_test_process_output_watchdog_stop(struct kunit *test)
cancel_delayed_work_sync(&work->property_validate_dwork);
}
-/*
- * Both callback_needed and watchdog_timer_needed set: both dworks are
- * scheduled independently.
+/**
+ * dm_test_process_output_callback_and_watchdog_needed - both dworks scheduled independently
+ * @test: KUnit test context
+ *
+ * When both callback_needed and watchdog_timer_needed are set,
+ * process_output() must schedule both dworks independently.
*/
static void dm_test_process_output_callback_and_watchdog_needed(struct kunit *test)
{
@@ -154,6 +405,18 @@ static void dm_test_process_output_callback_and_watchdog_needed(struct kunit *te
/* End of tests for process_output() */
static struct kunit_case dm_hdcp_test_cases[] = {
+ /* hdcp_get_content_protection_from_status() */
+ KUNIT_CASE(dm_test_hdcp_get_cp_disabled_returns_desired),
+ KUNIT_CASE(dm_test_hdcp_get_cp_type0_returns_enabled),
+ KUNIT_CASE(dm_test_hdcp_get_cp_type1_returns_enabled),
+ KUNIT_CASE(dm_test_hdcp_get_cp_type1_rejects_type0_status),
+ KUNIT_CASE(dm_test_hdcp_get_cp_type0_rejects_type1_status),
+ /* hdcp_get_link_display_adjustments() */
+ KUNIT_CASE(dm_test_hdcp_get_adjustments_disable_authentication),
+ KUNIT_CASE(dm_test_hdcp_get_adjustments_type0_policy),
+ KUNIT_CASE(dm_test_hdcp_get_adjustments_type1_policy),
+ KUNIT_CASE(dm_test_hdcp_get_adjustments_fused_io_enables_fw_check),
+ /* process_output() */
KUNIT_CASE(dm_test_process_output_property_validate_always_scheduled),
KUNIT_CASE(dm_test_process_output_callback_needed),
KUNIT_CASE(dm_test_process_output_callback_stop),
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 15/24] drm/amd/display: Restore periodic detection for DCN35
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (13 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 14/24] drm/amd/display: Extract HDCP testable helpers for KUnit Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 16/24] drm/amd/display: Remove duplicate pp_rn_set_wm_ranges Aurabindo Pillai
` (9 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Nicholas Kazlauskas
From: Ivan Lipski <ivan.lipski@amd.com>
[Why&How]
Periodic detection callbacks from DCN35 was removed for higher IPS
residency causing some displays to fail to recover after DPMS sleep. The
monitors bounces HPD ~1.2s after link training, and without periodic
detection the system enters IPS with no mechanism to wake and rediscover
the display.
Restore the periodic detection calls in dcn35_clk_mgr for now. It should
be replaced with a proper IPS-aware solution long term using DMUB.
Also remove it from dcn31 and dcn314_clk_mgr.c since they do not have IPS,
thus should not affect them.
Fixes: 3f6c060846be ("drm/amd/display: Remove periodic detection callbacks from dcn35+")
Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5318
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 --
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 2 --
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 2 ++
3 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
index 00c4be7c3aa4..ff47af3854b6 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
@@ -158,7 +158,6 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn31_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
@@ -184,7 +183,6 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn31_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
index dd6f11ecb9c9..24f6304011ae 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
@@ -230,7 +230,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn314_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
@@ -255,7 +254,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn314_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
index 103013e2a0de..a69824e1eb26 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -419,6 +419,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn35_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
+ dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
@@ -438,6 +439,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn35_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
+ dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 16/24] drm/amd/display: Remove duplicate pp_rn_set_wm_ranges
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (14 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 15/24] drm/amd/display: Restore periodic detection for DCN35 Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 17/24] drm/amd/display: Add KUnit tests for amdgpu_dm_pp_smu Aurabindo Pillai
` (8 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Remove pp_rn_set_wm_ranges and reuse the identical
pp_nv_set_wm_ranges for the DCN_VERSION_2_1 case instead.
Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index 2cdb8fea504a..2fda6fbed88f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -686,17 +686,6 @@ static enum pp_smu_status pp_rn_get_dpm_clock_table(
return PP_SMU_RESULT_OK;
}
-static enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp,
- struct pp_smu_wm_range_sets *ranges)
-{
- const struct dc_context *ctx = pp->dm;
- struct amdgpu_device *adev = ctx->driver_context;
-
- amdgpu_dpm_set_watermarks_for_clocks_ranges(adev, ranges);
-
- return PP_SMU_RESULT_OK;
-}
-
void dm_pp_get_funcs(
struct dc_context *ctx,
struct pp_smu_funcs *funcs)
@@ -743,7 +732,7 @@ void dm_pp_get_funcs(
case DCN_VERSION_2_1:
funcs->ctx.ver = PP_SMU_VER_RN;
funcs->rn_funcs.pp_smu.dm = ctx;
- funcs->rn_funcs.set_wm_ranges = pp_rn_set_wm_ranges;
+ funcs->rn_funcs.set_wm_ranges = pp_nv_set_wm_ranges;
funcs->rn_funcs.get_dpm_clock_table = pp_rn_get_dpm_clock_table;
break;
default:
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 17/24] drm/amd/display: Add KUnit tests for amdgpu_dm_pp_smu
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (15 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 16/24] drm/amd/display: Remove duplicate pp_rn_set_wm_ranges Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 18/24] drm/amd/display: Add detect reason to handle_hpd_irq_helper Aurabindo Pillai
` (7 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Add KUnit tests for two functions in amdgpu_dm_pp_smu.c:
get_default_clock_levels and dc_to_pp_clock_type.
Assisted-by: Copilot:Claude-Opus-4.6
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 8 +-
.../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h | 16 ++
.../drm/amd/display/amdgpu_dm/tests/Makefile | 2 +
.../amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c | 241 ++++++++++++++++++
4 files changed, 265 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index 2fda6fbed88f..ca7141dbdf6a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -33,6 +33,8 @@
#include "amdgpu_dm_irq.h"
#include "amdgpu_pm.h"
#include "dm_pp_smu.h"
+#include "amdgpu_dm_kunit_helpers.h"
+#include "amdgpu_dm_pp_smu.h"
bool dm_pp_apply_display_requirements(
const struct dc_context *ctx,
@@ -109,7 +111,7 @@ bool dm_pp_apply_display_requirements(
return true;
}
-static void get_default_clock_levels(
+STATIC_IFN_KUNIT void get_default_clock_levels(
enum dm_pp_clock_type clk_type,
struct dm_pp_clock_levels *clks)
{
@@ -140,8 +142,9 @@ static void get_default_clock_levels(
break;
}
}
+EXPORT_IF_KUNIT(get_default_clock_levels);
-static enum amd_pp_clock_type dc_to_pp_clock_type(
+STATIC_IFN_KUNIT enum amd_pp_clock_type dc_to_pp_clock_type(
enum dm_pp_clock_type dm_pp_clk_type)
{
enum amd_pp_clock_type amd_pp_clk_type = 0;
@@ -182,6 +185,7 @@ static enum amd_pp_clock_type dc_to_pp_clock_type(
return amd_pp_clk_type;
}
+EXPORT_IF_KUNIT(dc_to_pp_clock_type);
static void pp_to_dc_clock_levels(
const struct amd_pp_clocks *pp_clks,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h
new file mode 100644
index 000000000000..827b60d5affe
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#ifndef __AMDGPU_DM_PP_SMU_H__
+#define __AMDGPU_DM_PP_SMU_H__
+
+#include "dm_pp_interface.h"
+
+#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
+void get_default_clock_levels(enum dm_pp_clock_type clk_type, struct dm_pp_clock_levels *clks);
+enum amd_pp_clock_type dc_to_pp_clock_type(enum dm_pp_clock_type dm_pp_clk_type);
+#endif
+
+#endif /* __AMDGPU_DM_PP_SMU_H__ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
index fe9f32c9bdde..4d2eb301c2af 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
@@ -8,6 +8,7 @@ ccflags-y += -I$(src)/../../include
ccflags-y += -I$(src)/../../modules/inc
ccflags-y += -I$(src)/../../dc
ccflags-y += -I$(src)/../../../amdgpu
+ccflags-y += -I$(src)/../../../include
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_crc_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_hdcp_test.o
@@ -18,3 +19,4 @@ obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_replay_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_ism_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_wb_test.o
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_mst_types_test.o
+obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_pp_smu_test.o
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c
new file mode 100644
index 000000000000..556473f55ebe
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * KUnit tests for amdgpu_dm_pp_smu.c
+ *
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#include <kunit/test.h>
+#include <linux/types.h>
+
+#include "dc.h"
+#include "amdgpu_mode.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_pp_smu.h"
+
+/* ---- Tests for get_default_clock_levels ---- */
+
+/**
+ * dm_test_default_clock_levels_display - Test display clock default levels
+ * @test: KUnit test context
+ *
+ * Verify that get_default_clock_levels populates 6 display clock levels
+ * with the expected frequencies in kHz.
+ */
+static void dm_test_default_clock_levels_display(struct kunit *test)
+{
+ struct dm_pp_clock_levels clks = { 0 };
+ uint32_t expected[] = { 300000, 400000, 496560, 626090, 685720, 757900 };
+ int i;
+
+ get_default_clock_levels(DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks);
+
+ KUNIT_EXPECT_EQ(test, clks.num_levels, 6U);
+ for (i = 0; i < 6; i++)
+ KUNIT_EXPECT_EQ(test, clks.clocks_in_khz[i], expected[i]);
+}
+
+/**
+ * dm_test_default_clock_levels_engine - Test engine clock default levels
+ * @test: KUnit test context
+ *
+ * Verify that get_default_clock_levels populates 6 engine clock levels
+ * with the expected frequencies in kHz.
+ */
+static void dm_test_default_clock_levels_engine(struct kunit *test)
+{
+ struct dm_pp_clock_levels clks = { 0 };
+ uint32_t expected[] = { 300000, 360000, 423530, 514290, 626090, 720000 };
+ int i;
+
+ get_default_clock_levels(DM_PP_CLOCK_TYPE_ENGINE_CLK, &clks);
+
+ KUNIT_EXPECT_EQ(test, clks.num_levels, 6U);
+ for (i = 0; i < 6; i++)
+ KUNIT_EXPECT_EQ(test, clks.clocks_in_khz[i], expected[i]);
+}
+
+/**
+ * dm_test_default_clock_levels_memory - Test memory clock default levels
+ * @test: KUnit test context
+ *
+ * Verify that get_default_clock_levels populates 2 memory clock levels
+ * with the expected frequencies in kHz.
+ */
+static void dm_test_default_clock_levels_memory(struct kunit *test)
+{
+ struct dm_pp_clock_levels clks = { 0 };
+
+ get_default_clock_levels(DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks);
+
+ KUNIT_EXPECT_EQ(test, clks.num_levels, 2U);
+ KUNIT_EXPECT_EQ(test, clks.clocks_in_khz[0], 333000U);
+ KUNIT_EXPECT_EQ(test, clks.clocks_in_khz[1], 800000U);
+}
+
+/**
+ * dm_test_default_clock_levels_unknown - Test unknown clock type default
+ * @test: KUnit test context
+ *
+ * Verify that get_default_clock_levels sets num_levels to 0 for an
+ * unrecognized clock type.
+ */
+static void dm_test_default_clock_levels_unknown(struct kunit *test)
+{
+ struct dm_pp_clock_levels clks = { 0 };
+
+ get_default_clock_levels(DM_PP_CLOCK_TYPE_FCLK, &clks);
+
+ KUNIT_EXPECT_EQ(test, clks.num_levels, 0U);
+}
+
+/* ---- Tests for dc_to_pp_clock_type ---- */
+
+/**
+ * dm_test_dc_to_pp_clock_type_display - Test display clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_DISPLAY_CLK maps to amd_pp_disp_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_display(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_DISPLAY_CLK),
+ (int)amd_pp_disp_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_engine - Test engine clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_ENGINE_CLK maps to amd_pp_sys_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_engine(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_ENGINE_CLK),
+ (int)amd_pp_sys_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_memory - Test memory clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_MEMORY_CLK maps to amd_pp_mem_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_memory(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_MEMORY_CLK),
+ (int)amd_pp_mem_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_dcefclk - Test DCEF clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_DCEFCLK maps to amd_pp_dcef_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_dcefclk(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_DCEFCLK),
+ (int)amd_pp_dcef_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_dcfclk - Test DCF clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_DCFCLK maps to amd_pp_dcf_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_dcfclk(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_DCFCLK),
+ (int)amd_pp_dcf_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_pixelclk - Test pixel clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_PIXELCLK maps to amd_pp_pixel_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_pixelclk(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_PIXELCLK),
+ (int)amd_pp_pixel_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_fclk - Test FCLK type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_FCLK maps to amd_pp_f_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_fclk(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_FCLK),
+ (int)amd_pp_f_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_phyclk - Test display PHY clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_DISPLAYPHYCLK maps to amd_pp_phy_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_phyclk(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_DISPLAYPHYCLK),
+ (int)amd_pp_phy_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_dppclk - Test DPP clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify DM_PP_CLOCK_TYPE_DPPCLK maps to amd_pp_dpp_clock.
+ */
+static void dm_test_dc_to_pp_clock_type_dppclk(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(DM_PP_CLOCK_TYPE_DPPCLK),
+ (int)amd_pp_dpp_clock);
+}
+
+/**
+ * dm_test_dc_to_pp_clock_type_invalid - Test invalid clock type mapping
+ * @test: KUnit test context
+ *
+ * Verify that an invalid clock type value maps to 0.
+ */
+static void dm_test_dc_to_pp_clock_type_invalid(struct kunit *test)
+{
+ KUNIT_EXPECT_EQ(test, (int)dc_to_pp_clock_type(0), 0);
+}
+
+static struct kunit_case dm_pp_smu_test_cases[] = {
+ /* get_default_clock_levels */
+ KUNIT_CASE(dm_test_default_clock_levels_display),
+ KUNIT_CASE(dm_test_default_clock_levels_engine),
+ KUNIT_CASE(dm_test_default_clock_levels_memory),
+ KUNIT_CASE(dm_test_default_clock_levels_unknown),
+ /* dc_to_pp_clock_type */
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_display),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_engine),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_memory),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_dcefclk),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_dcfclk),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_pixelclk),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_fclk),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_phyclk),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_dppclk),
+ KUNIT_CASE(dm_test_dc_to_pp_clock_type_invalid),
+ {}
+};
+
+static struct kunit_suite dm_pp_smu_test_suite = {
+ .name = "amdgpu_dm_pp_smu",
+ .test_cases = dm_pp_smu_test_cases,
+};
+
+kunit_test_suite(dm_pp_smu_test_suite);
+
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_pp_smu");
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 18/24] drm/amd/display: Add detect reason to handle_hpd_irq_helper
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (16 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 17/24] drm/amd/display: Add KUnit tests for amdgpu_dm_pp_smu Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 19/24] drm/amd/display: Use handle_hpd_irq_helper for HPD RX Aurabindo Pillai
` (6 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Timur Kristóf
From: Timur Kristóf <timur.kristof@gmail.com>
This makes it possible to reuse the function for other purposes
in the next few commits, such as HPD RX.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 46993b5ae688..52cfe32f14b8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -242,7 +242,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state);
static int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state);
-static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector);
+static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector,
+ enum dc_detect_reason reason);
static void handle_hpd_rx_irq(void *param);
static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
@@ -890,7 +891,7 @@ static void dmub_hpd_callback(struct amdgpu_device *adev,
if (notify->type == DMUB_NOTIFICATION_HPD) {
if (hpd_aconnector->dc_link->hpd_status == (notify->hpd_status == DP_HPD_PLUG))
drm_warn(adev_to_drm(adev), "DMUB reported hpd status unchanged. link_index=%u\n", link_index);
- handle_hpd_irq_helper(hpd_aconnector);
+ handle_hpd_irq_helper(hpd_aconnector, DETECT_REASON_HPD);
} else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ) {
handle_hpd_rx_irq(hpd_aconnector);
}
@@ -4355,7 +4356,8 @@ static void hdmi_hpd_debounce_work(struct work_struct *work)
}
}
-static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
+static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector,
+ enum dc_detect_reason reason)
{
struct drm_connector *connector = &aconnector->base;
struct drm_device *dev = connector->dev;
@@ -4402,7 +4404,8 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
dm_restore_drm_connector_state(dev, connector);
drm_modeset_unlock_all(dev);
- if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
+ if (aconnector->base.force == DRM_FORCE_UNSPECIFIED ||
+ reason == DETECT_REASON_HPDRX)
drm_kms_helper_connector_hotplug_event(connector);
} else if (debounce_required) {
/*
@@ -4434,7 +4437,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
scoped_guard(mutex, &adev->dm.dc_lock) {
dc_exit_ips_for_hw_access(dc);
- ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
+ ret = dc_link_detect(aconnector->dc_link, reason);
}
if (ret) {
/* w/a delay for certain panels */
@@ -4445,7 +4448,8 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
dm_restore_drm_connector_state(dev, connector);
drm_modeset_unlock_all(dev);
- if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
+ if (aconnector->base.force == DRM_FORCE_UNSPECIFIED ||
+ reason == DETECT_REASON_HPDRX)
drm_kms_helper_connector_hotplug_event(connector);
}
}
@@ -4455,7 +4459,7 @@ static void handle_hpd_irq(void *param)
{
struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param;
- handle_hpd_irq_helper(aconnector);
+ handle_hpd_irq_helper(aconnector, DETECT_REASON_HPD);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 19/24] drm/amd/display: Use handle_hpd_irq_helper for HPD RX
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (17 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 18/24] drm/amd/display: Add detect reason to handle_hpd_irq_helper Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 20/24] drm/amd/display: Always create delayed HPD work queue Aurabindo Pillai
` (5 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Timur Kristóf
From: Timur Kristóf <timur.kristof@gmail.com>
Remove duplicated code and just call handle_hpd_irq_helper
with the appropriate detect reason.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 41 +------------------
1 file changed, 1 insertion(+), 40 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 52cfe32f14b8..e1d23dd3c2a7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4491,14 +4491,12 @@ static void handle_hpd_rx_irq(void *param)
struct dc_link *dc_link = aconnector->dc_link;
bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
bool result = false;
- enum dc_connection_type new_connection_type = dc_connection_none;
struct amdgpu_device *adev = drm_to_adev(dev);
union hpd_irq_data hpd_irq_data;
bool link_loss = false;
bool has_left_work = false;
int idx = dc_link->link_index;
struct hpd_rx_irq_offload_work_queue *offload_wq = &adev->dm.hpd_rx_offload_wq[idx];
- struct dc *dc = aconnector->dc_link->ctx->dc;
memset(&hpd_irq_data, 0, sizeof(hpd_irq_data));
@@ -4567,44 +4565,7 @@ static void handle_hpd_rx_irq(void *param)
out:
if (result && !is_mst_root_connector) {
/* Downstream Port status changed. */
- if (!dc_link_detect_connection_type(dc_link, &new_connection_type))
- drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n");
-
- if (aconnector->base.force && new_connection_type == dc_connection_none) {
- emulated_link_detect(dc_link);
-
- if (aconnector->fake_enable)
- aconnector->fake_enable = false;
-
- amdgpu_dm_update_connector_after_detect(aconnector);
-
-
- drm_modeset_lock_all(dev);
- dm_restore_drm_connector_state(dev, connector);
- drm_modeset_unlock_all(dev);
-
- drm_kms_helper_connector_hotplug_event(connector);
- } else {
- bool ret = false;
-
- mutex_lock(&adev->dm.dc_lock);
- dc_exit_ips_for_hw_access(dc);
- ret = dc_link_detect(dc_link, DETECT_REASON_HPDRX);
- mutex_unlock(&adev->dm.dc_lock);
-
- if (ret) {
- if (aconnector->fake_enable)
- aconnector->fake_enable = false;
-
- amdgpu_dm_update_connector_after_detect(aconnector);
-
- drm_modeset_lock_all(dev);
- dm_restore_drm_connector_state(dev, connector);
- drm_modeset_unlock_all(dev);
-
- drm_kms_helper_connector_hotplug_event(connector);
- }
- }
+ handle_hpd_irq_helper(aconnector, DETECT_REASON_HPDRX);
}
if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) {
if (adev->dm.hdcp_workqueue)
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 20/24] drm/amd/display: Always create delayed HPD work queue
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (18 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 19/24] drm/amd/display: Use handle_hpd_irq_helper for HPD RX Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 21/24] drm/amd/display: Retry link detection on hotplug Aurabindo Pillai
` (4 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Timur Kristóf
From: Timur Kristóf <timur.kristof@gmail.com>
Not just when DMUB outbox is supported.
It will be used for normal HPD events too.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index e1d23dd3c2a7..d1b1eb67d937 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2240,6 +2240,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
create_singlethread_workqueue("dm_vblank_control_workqueue");
if (!adev->dm.vblank_control_workqueue)
drm_err(adev_to_drm(adev), "failed to initialize vblank_workqueue.\n");
+
+ adev->dm.delayed_hpd_wq = create_singlethread_workqueue("amdgpu_dm_hpd_wq");
+ if (!adev->dm.delayed_hpd_wq) {
+ drm_err(adev_to_drm(adev), "failed to create hpd offload workqueue.\n");
+ goto error;
+ }
}
if (adev->dm.dc->caps.ips_support &&
@@ -2274,12 +2280,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
goto error;
}
- adev->dm.delayed_hpd_wq = create_singlethread_workqueue("amdgpu_dm_hpd_wq");
- if (!adev->dm.delayed_hpd_wq) {
- drm_err(adev_to_drm(adev), "failed to create hpd offload workqueue.\n");
- goto error;
- }
-
amdgpu_dm_outbox_init(adev);
if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_AUX_REPLY,
dmub_aux_setconfig_callback, false)) {
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 21/24] drm/amd/display: Retry link detection on hotplug
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (19 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 20/24] drm/amd/display: Always create delayed HPD work queue Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-05 16:10 ` Zuo, Jerry
2026-06-04 14:52 ` [PATCH 22/24] drm/amd/display: Retry link detection on resume and boot Aurabindo Pillai
` (3 subsequent siblings)
24 siblings, 1 reply; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Timur Kristóf
From: Timur Kristóf <timur.kristof@gmail.com>
When dc_link_detect_connection_type thinks that a display is
connected, but dc_link_detect failed, enqueue delayed work to
retry the link detection again.
Useful when eg. HPD pin is high but the display isn't ready and
didn't respond to DDC.
- The display is "slow to wake up", ie. DDC isn't ready,
for example we couldn't read EDID. Can happen with any
connector type with certain "slow" displays.
Some displays may take up to 15~20 sec or more to wake up.
- On hotplug, the HPD pin may make contact before the DDC pins,
so we couldn't read the EDID. This most often happens with
DVI connectors, rarely with HDMI. It is not impossible but
extremely rare with other connector types.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 138 ++++++++++++++++++
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 16 ++
2 files changed, 154 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d1b1eb67d937..40295a5edbec 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -161,6 +161,17 @@ MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB);
#define FIRMWARE_DCN_42B_DMUB "amdgpu/dcn_4_2_1_dmcub.bin"
MODULE_FIRMWARE(FIRMWARE_DCN_42B_DMUB);
+/**
+ * define AMDGPU_DM_HPD_MAX_NUM_RETRIES - maximum amount of retries for hotplug detection
+ */
+#define AMDGPU_DM_HPD_MAX_NUM_RETRIES 5
+
+/**
+ * define AMDGPU_DM_HPD_RETRY_DELAY_MSEC - millisecond delay between hotplug detection retries
+ */
+#define AMDGPU_DM_HPD_RETRY_DELAY_MSEC 1500
+
+
/**
* DOC: overview
*
@@ -959,6 +970,125 @@ static void dm_handle_hpd_work(struct work_struct *work)
}
+/**
+ * dm_handle_delayed_hpd_work() - Handle delayed HPD (hotplug detection)
+ *
+ * @w: Base work item structure
+ *
+ * Used for retrying HPD after a delay. Just calls the normal HPD helper.
+ */
+static void dm_handle_delayed_hpd_work(struct work_struct *work)
+{
+ struct delayed_work *dw = container_of(work, struct delayed_work, work);
+ struct delayed_hpd_work *w = container_of(dw, struct delayed_hpd_work, work);
+ struct amdgpu_dm_connector *aconn = w->aconn;
+ enum dc_detect_reason reason = w->reason;
+
+ kfree(w);
+ handle_hpd_irq_helper(aconn, reason);
+}
+
+/**
+ * dm_cancel_delayed_hpd_work() - Cancel pending hotplug detection work for a connector
+ *
+ * @aconnector: Connector on which the HPD event occurred
+ */
+static void dm_cancel_delayed_hpd_work(struct amdgpu_dm_connector *aconnector)
+{
+ if (!aconnector || !aconnector->delayed_hpd_work)
+ return;
+
+ cancel_delayed_work(&aconnector->delayed_hpd_work->work);
+ aconnector->delayed_hpd_work = NULL;
+}
+
+/**
+ * dm_cancel_all_delayed_hpd_work() - Cancel all pending hotplug detection work on the device
+ *
+ * @dev: DRM device pointer
+ */
+static void dm_cancel_all_delayed_hpd_work(struct drm_device *dev)
+{
+ struct drm_connector *connector;
+ struct drm_connector_list_iter iter;
+
+ drm_connector_list_iter_begin(dev, &iter);
+ drm_for_each_connector_iter(connector, &iter) {
+ if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+ continue;
+
+ dm_cancel_delayed_hpd_work(to_amdgpu_dm_connector(connector));
+ }
+ drm_connector_list_iter_end(&iter);
+}
+
+/**
+ * dm_queue_delayed_hpd_work() - Enqueue delayed work to handle hotplug detection
+ *
+ * @aconnector: Connector on which the HPD event occurred
+ * @reason: Reason why we are attempting the HPD
+ * @msecs: Millisecond delay after which the delayed work is going to happen
+ *
+ * When dc_link_detect_connection_type thinks that a display is connected,
+ * but dc_link_detect failed, enqueue delayed work to retry the link
+ * detection again.
+ *
+ * Useful when eg. HPD pin is high but the display isn't ready and
+ * didn't respond to DDC.
+ *
+ * - On boot or suspend/resume, the display is "slow to wake up",
+ * ie. DDC isn't ready, for example we couldn't read DP link caps or EDID.
+ * Can happen to any connector with certain "slow" displays.
+ *
+ * - On hotplug, the HPD pin may make contact before the DDC pins,
+ * so we couldn't read the EDID. Can happen to any connector but
+ * most often to DVI and sometimes to HDMI (rarely to DP).
+ *
+ */
+static void dm_queue_delayed_hpd_work(struct amdgpu_dm_connector *aconnector,
+ const enum dc_detect_reason reason,
+ const unsigned int msecs)
+{
+ struct drm_device *dev = aconnector->base.dev;
+ struct amdgpu_device *adev = drm_to_adev(dev);
+ struct delayed_hpd_work *w;
+
+ if (!aconnector || !aconnector->dc_link ||
+ aconnector->dc_link->type == dc_connection_none)
+ return;
+
+ /* Don't retry polled connectors, the polling is going to detect it. */
+ if (aconnector->base.polled != DRM_CONNECTOR_POLL_HPD)
+ return;
+
+ ++aconnector->num_hpd_retries;
+
+ drm_dbg(dev, "Can't detect link on %s on try %d\n",
+ aconnector->base.name, aconnector->num_hpd_retries);
+
+ if (aconnector->num_hpd_retries > AMDGPU_DM_HPD_MAX_NUM_RETRIES) {
+ drm_warn(dev, "Too many retries on %s: %d, giving up\n",
+ aconnector->base.name, aconnector->num_hpd_retries);
+ aconnector->num_hpd_retries = 0;
+ return;
+ }
+
+ w = kzalloc(sizeof(*w), GFP_ATOMIC);
+
+ if (!w)
+ return;
+
+ INIT_DELAYED_WORK(&w->work, dm_handle_delayed_hpd_work);
+ w->aconn = aconnector;
+ w->reason = reason;
+ aconnector->delayed_hpd_work = w;
+
+ drm_warn(dev, "Enqueueing next retry on %s\n",
+ aconnector->base.name);
+ queue_delayed_work(adev->dm.delayed_hpd_wq, &w->work,
+ msecs_to_jiffies(msecs));
+}
+
static const char *dmub_notification_type_str(enum dmub_notification_type e)
{
switch (e) {
@@ -3249,6 +3379,7 @@ static int dm_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
+ dm_cancel_all_delayed_hpd_work(&adev->ddev);
amdgpu_dm_hpd_fini(adev);
amdgpu_dm_irq_fini(adev);
@@ -3422,6 +3553,8 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
struct amdgpu_display_manager *dm = &adev->dm;
+ dm_cancel_all_delayed_hpd_work(&adev->ddev);
+
if (amdgpu_in_reset(adev)) {
enum dc_status res;
@@ -4451,6 +4584,9 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector,
if (aconnector->base.force == DRM_FORCE_UNSPECIFIED ||
reason == DETECT_REASON_HPDRX)
drm_kms_helper_connector_hotplug_event(connector);
+ } else {
+ dm_queue_delayed_hpd_work(aconnector, reason,
+ AMDGPU_DM_HPD_RETRY_DELAY_MSEC);
}
}
}
@@ -4459,6 +4595,8 @@ static void handle_hpd_irq(void *param)
{
struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param;
+ /* Cancel any pending work */
+ dm_cancel_delayed_hpd_work(aconnector);
handle_hpd_irq_helper(aconnector, DETECT_REASON_HPD);
}
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 7d37c1612131..9a66c9e2b78d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -136,6 +136,18 @@ struct dmub_hpd_work {
struct amdgpu_device *adev;
};
+/**
+ * struct delayed_hpd_work - Handle delayed HPD (hot plug detection) work
+ *
+ * @work: Base structure, kernel work data for the work event
+ * @aconn: Pointer to connector where the HPD event happened
+ */
+struct delayed_hpd_work {
+ struct delayed_work work;
+ struct amdgpu_dm_connector *aconn;
+ enum dc_detect_reason reason;
+};
+
/**
* struct vblank_control_work - Work data for vblank control
* @work: Kernel work data for the work event
@@ -801,6 +813,10 @@ struct amdgpu_dm_connector {
/* number of modes generated from EDID at 'dc_sink' */
int num_modes;
+ /* number of retries on hot plug detection */
+ int num_hpd_retries;
+ struct delayed_hpd_work *delayed_hpd_work;
+
/* The 'old' sink - before an HPD.
* The 'current' sink is in dc_link->sink. */
struct dc_sink *dc_sink;
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 22/24] drm/amd/display: Retry link detection on resume and boot
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (20 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 21/24] drm/amd/display: Retry link detection on hotplug Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 23/24] drm/amd/display: fix compressed buffer config routine waiting time Aurabindo Pillai
` (2 subsequent siblings)
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Timur Kristóf
From: Timur Kristóf <timur.kristof@gmail.com>
Link detection may fail after suspend/resume when the display
is "slow to wake up", and it may happen on boot as well.
Let's retry link detection in those cases too.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 40295a5edbec..b19bad9fcd12 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4010,6 +4010,10 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
if (ret) {
/* w/a delay for certain panels */
apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink);
+ } else {
+ dm_queue_delayed_hpd_work(aconnector,
+ DETECT_REASON_RESUMEFROMS3S4,
+ AMDGPU_DM_HPD_RETRY_DELAY_MSEC);
}
}
@@ -6038,6 +6042,10 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
link->dpcd_caps.psr_info.psr_dpcd_caps.raw,
link->dpcd_caps.psr_info.psr2_su_y_granularity_cap);
}
+ } else {
+ dm_queue_delayed_hpd_work(aconnector,
+ DETECT_REASON_BOOT,
+ AMDGPU_DM_HPD_RETRY_DELAY_MSEC);
}
}
amdgpu_set_panel_orientation(&aconnector->base);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 23/24] drm/amd/display: fix compressed buffer config routine waiting time
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (21 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 22/24] drm/amd/display: Retry link detection on resume and boot Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 24/24] drm/amd/display: Promote DC to 3.2.385 Aurabindo Pillai
2026-06-08 13:25 ` [PATCH 00/24] DC Patches for 8 June 2026 Wheeler, Daniel
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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, Antonio Quartulli
From: Antonio Quartulli <antonio@mandelbit.com>
Replace the four open-coded REG_WAIT calls with calls to
dcn31_wait_for_det_apply() so the compressed buffer (compbuf) sizing
path waits long enough for the DET size update to take effect, and the
wait timing stays consistent across the driver.
No functional change beyond the corrected timeout.
Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
---
.../gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
index 79cb506be5cb..cbcd22789013 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
@@ -138,10 +138,10 @@ static void dcn31_program_compbuf_size(struct hubbub *hubbub, unsigned int compb
if (safe_to_increase || compbuf_size_segments <= hubbub2->compbuf_size_segments) {
if (compbuf_size_segments > hubbub2->compbuf_size_segments) {
- REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100);
- REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100);
- REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100);
- REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100);
+ dcn31_wait_for_det_apply(hubbub, 0);
+ dcn31_wait_for_det_apply(hubbub, 1);
+ dcn31_wait_for_det_apply(hubbub, 2);
+ dcn31_wait_for_det_apply(hubbub, 3);
}
/* Should never be hit, if it is we have an erroneous hw config*/
ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 24/24] drm/amd/display: Promote DC to 3.2.385
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (22 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 23/24] drm/amd/display: fix compressed buffer config routine waiting time Aurabindo Pillai
@ 2026-06-04 14:52 ` Aurabindo Pillai
2026-06-08 13:25 ` [PATCH 00/24] DC Patches for 8 June 2026 Wheeler, Daniel
24 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-04 14:52 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>
Summary:
* Display connectivity & HPD:
- Retry link detection on resume, boot, and hotplug
- Refactor HPD RX to use handle_hpd_irq_helper with detect reason
- Always create delayed HPD work queue
- Restore periodic detection for DCN35
* DCN42B support:
- Fix DCN42B version detection
- Add DCN42B to dml21_translation_helper
* KUnit testing infrastructure:
- Add KUnit tests for amdgpu_dm_pp_smu, amdgpu_dm_mst_types,
and writeback connector
- Extract HDCP and DPRX CRC transition helpers for KUnit
- Export symbols for KUnit test modules
- Enable warnings as errors for KUnit tests
* Fixes & cleanups:
- Fix compressed buffer config routine waiting time
- Fix incorrect logic in CRC source handling
- Fix writeback format loop and variable init
- Fix max dispclk_khz/dppclk_khz double 1000
- Remove duplicate pp_rn_set_wm_ranges
- Remove dead code in dm_dp_mst_get_modes
- Remove redundant code in amdgpu_dm_replay
- Skip PHY SSC reduction on some 8K panels
- Temp disable repeater FGCG as workaround
- Deprecate DMUB register offload functionality
- TEST_HARNESS FSN could be 0
* Firmware:
- DMUB FW promotion to 0.1.62.0
Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Reviewed-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 d74776802418..b8ac462a676a 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -65,7 +65,7 @@ struct dcn_dsc_reg_state;
struct dcn_optc_reg_state;
struct dcn_dccg_reg_state;
-#define DC_VER "3.2.384"
+#define DC_VER "3.2.385"
/**
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* RE: [PATCH 21/24] drm/amd/display: Retry link detection on hotplug
2026-06-04 14:52 ` [PATCH 21/24] drm/amd/display: Retry link detection on hotplug Aurabindo Pillai
@ 2026-06-05 16:10 ` Zuo, Jerry
2026-06-05 18:26 ` Aurabindo Pillai
` (2 more replies)
0 siblings, 3 replies; 30+ messages in thread
From: Zuo, Jerry @ 2026-06-05 16:10 UTC (permalink / raw)
To: Pillai, Aurabindo, amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry, Li, Sun peng (Leo), Pillai, Aurabindo, Li, Roman,
Lin, Wayne, Chung, ChiaHsuan (Tom), Wheeler, Daniel, Wu, Ray,
LIPSKI, IVAN, Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu,
Timur Kristóf
AMD General
Hi Timur:
Please let me know whether you have validated the sequence by any SST and HDMI monitor. Basically it is to confirm the link retry workqueue is getting executed with hotplug and dpms use cases without introducing side effect. We've tested locally, but we don't see any link retry workqueue is getting executed by either SST or HDMI monitors. That makes us hard to validate the new error handling logic. It would be perfect that if you have done that at your local setup to confirm the new logic is regression-free for SST and HDMI.
Apart from that, we find a regression in MST. MST has its own detection logic and should be separated from SST and HDMI.
Regards,
Jerry
> -----Original Message-----
> From: Aurabindo Pillai <aurabindo.pillai@amd.com>
> Sent: Thursday, June 4, 2026 10:52
> To: amd-gfx@lists.freedesktop.org
> Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo)
> <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>; Li,
> Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung,
> ChiaHsuan (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry
> <Jerry.Zuo@amd.com>; Wheeler, Daniel <Daniel.Wheeler@amd.com>; Wu,
> Ray <Ray.Wu@amd.com>; LIPSKI, IVAN <IVAN.LIPSKI@amd.com>; Hung, Alex
> <Alex.Hung@amd.com>; Lin, Ping Lei <PingLei.Lin@amd.com>; Chen, Chen-
> Yu <Chen-Yu.Chen@amd.com>; Timur Kristóf <timur.kristof@gmail.com>
> Subject: [PATCH 21/24] drm/amd/display: Retry link detection on hotplug
>
> From: Timur Kristóf <timur.kristof@gmail.com>
>
> When dc_link_detect_connection_type thinks that a display is connected, but
> dc_link_detect failed, enqueue delayed work to retry the link detection again.
>
> Useful when eg. HPD pin is high but the display isn't ready and didn't respond
> to DDC.
>
> - The display is "slow to wake up", ie. DDC isn't ready,
> for example we couldn't read EDID. Can happen with any
> connector type with certain "slow" displays.
> Some displays may take up to 15~20 sec or more to wake up.
>
> - On hotplug, the HPD pin may make contact before the DDC pins,
> so we couldn't read the EDID. This most often happens with
> DVI connectors, rarely with HDMI. It is not impossible but
> extremely rare with other connector types.
>
> Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
> Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
> Reviewed-by: Alex Hung <alex.hung@amd.com>
> ---
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 138
> ++++++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> | 16 ++
> 2 files changed, 154 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index d1b1eb67d937..40295a5edbec 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -161,6 +161,17 @@ MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB);
> #define FIRMWARE_DCN_42B_DMUB "amdgpu/dcn_4_2_1_dmcub.bin"
> MODULE_FIRMWARE(FIRMWARE_DCN_42B_DMUB);
>
> +/**
> + * define AMDGPU_DM_HPD_MAX_NUM_RETRIES - maximum amount of
> retries for
> +hotplug detection */ #define AMDGPU_DM_HPD_MAX_NUM_RETRIES 5
> +
> +/**
> + * define AMDGPU_DM_HPD_RETRY_DELAY_MSEC - millisecond delay
> between
> +hotplug detection retries */ #define
> AMDGPU_DM_HPD_RETRY_DELAY_MSEC
> +1500
> +
> +
> /**
> * DOC: overview
> *
> @@ -959,6 +970,125 @@ static void dm_handle_hpd_work(struct
> work_struct *work)
>
> }
>
> +/**
> + * dm_handle_delayed_hpd_work() - Handle delayed HPD (hotplug
> +detection)
> + *
> + * @w: Base work item structure
> + *
> + * Used for retrying HPD after a delay. Just calls the normal HPD helper.
> + */
> +static void dm_handle_delayed_hpd_work(struct work_struct *work) {
> + struct delayed_work *dw = container_of(work, struct delayed_work,
> work);
> + struct delayed_hpd_work *w = container_of(dw, struct
> delayed_hpd_work, work);
> + struct amdgpu_dm_connector *aconn = w->aconn;
> + enum dc_detect_reason reason = w->reason;
> +
> + kfree(w);
> + handle_hpd_irq_helper(aconn, reason);
> +}
> +
> +/**
> + * dm_cancel_delayed_hpd_work() - Cancel pending hotplug detection work
> +for a connector
> + *
> + * @aconnector: Connector on which the HPD event occurred */ static
> +void dm_cancel_delayed_hpd_work(struct amdgpu_dm_connector
> *aconnector)
> +{
> + if (!aconnector || !aconnector->delayed_hpd_work)
> + return;
> +
> + cancel_delayed_work(&aconnector->delayed_hpd_work->work);
> + aconnector->delayed_hpd_work = NULL;
> +}
> +
> +/**
> + * dm_cancel_all_delayed_hpd_work() - Cancel all pending hotplug
> +detection work on the device
> + *
> + * @dev: DRM device pointer
> + */
> +static void dm_cancel_all_delayed_hpd_work(struct drm_device *dev) {
> + struct drm_connector *connector;
> + struct drm_connector_list_iter iter;
> +
> + drm_connector_list_iter_begin(dev, &iter);
> + drm_for_each_connector_iter(connector, &iter) {
> + if (connector->connector_type ==
> DRM_MODE_CONNECTOR_WRITEBACK)
> + continue;
> +
> +
> dm_cancel_delayed_hpd_work(to_amdgpu_dm_connector(connecto
> r));
> + }
> + drm_connector_list_iter_end(&iter);
> +}
> +
> +/**
> + * dm_queue_delayed_hpd_work() - Enqueue delayed work to handle
> hotplug
> +detection
> + *
> + * @aconnector: Connector on which the HPD event occurred
> + * @reason: Reason why we are attempting the HPD
> + * @msecs: Millisecond delay after which the delayed work is going to
> +happen
> + *
> + * When dc_link_detect_connection_type thinks that a display is
> +connected,
> + * but dc_link_detect failed, enqueue delayed work to retry the link
> + * detection again.
> + *
> + * Useful when eg. HPD pin is high but the display isn't ready and
> + * didn't respond to DDC.
> + *
> + * - On boot or suspend/resume, the display is "slow to wake up",
> + * ie. DDC isn't ready, for example we couldn't read DP link caps or EDID.
> + * Can happen to any connector with certain "slow" displays.
> + *
> + * - On hotplug, the HPD pin may make contact before the DDC pins,
> + * so we couldn't read the EDID. Can happen to any connector but
> + * most often to DVI and sometimes to HDMI (rarely to DP).
> + *
> + */
> +static void dm_queue_delayed_hpd_work(struct amdgpu_dm_connector
> *aconnector,
> + const enum dc_detect_reason reason,
> + const unsigned int msecs)
> +{
> + struct drm_device *dev = aconnector->base.dev;
> + struct amdgpu_device *adev = drm_to_adev(dev);
> + struct delayed_hpd_work *w;
> +
> + if (!aconnector || !aconnector->dc_link ||
> + aconnector->dc_link->type == dc_connection_none)
> + return;
> +
> + /* Don't retry polled connectors, the polling is going to detect it. */
> + if (aconnector->base.polled != DRM_CONNECTOR_POLL_HPD)
> + return;
> +
> + ++aconnector->num_hpd_retries;
> +
> + drm_dbg(dev, "Can't detect link on %s on try %d\n",
> + aconnector->base.name, aconnector->num_hpd_retries);
> +
> + if (aconnector->num_hpd_retries >
> AMDGPU_DM_HPD_MAX_NUM_RETRIES) {
> + drm_warn(dev, "Too many retries on %s: %d, giving up\n",
> + aconnector->base.name, aconnector-
> >num_hpd_retries);
> + aconnector->num_hpd_retries = 0;
> + return;
> + }
> +
> + w = kzalloc(sizeof(*w), GFP_ATOMIC);
> +
> + if (!w)
> + return;
> +
> + INIT_DELAYED_WORK(&w->work, dm_handle_delayed_hpd_work);
> + w->aconn = aconnector;
> + w->reason = reason;
> + aconnector->delayed_hpd_work = w;
> +
> + drm_warn(dev, "Enqueueing next retry on %s\n",
> + aconnector->base.name);
> + queue_delayed_work(adev->dm.delayed_hpd_wq, &w->work,
> + msecs_to_jiffies(msecs));
> +}
> +
> static const char *dmub_notification_type_str(enum dmub_notification_type
> e) {
> switch (e) {
> @@ -3249,6 +3379,7 @@ static int dm_hw_fini(struct amdgpu_ip_block
> *ip_block) {
> struct amdgpu_device *adev = ip_block->adev;
>
> + dm_cancel_all_delayed_hpd_work(&adev->ddev);
> amdgpu_dm_hpd_fini(adev);
>
> amdgpu_dm_irq_fini(adev);
> @@ -3422,6 +3553,8 @@ static int dm_suspend(struct amdgpu_ip_block
> *ip_block)
> struct amdgpu_device *adev = ip_block->adev;
> struct amdgpu_display_manager *dm = &adev->dm;
>
> + dm_cancel_all_delayed_hpd_work(&adev->ddev);
> +
> if (amdgpu_in_reset(adev)) {
> enum dc_status res;
>
> @@ -4451,6 +4584,9 @@ static void handle_hpd_irq_helper(struct
> amdgpu_dm_connector *aconnector,
> if (aconnector->base.force ==
> DRM_FORCE_UNSPECIFIED ||
> reason == DETECT_REASON_HPDRX)
>
> drm_kms_helper_connector_hotplug_event(connector);
> + } else {
We need to return here if aconnector->mst_mgr.mst_state is set.
> + dm_queue_delayed_hpd_work(aconnector, reason,
> +
> AMDGPU_DM_HPD_RETRY_DELAY_MSEC);
> }
> }
> }
> @@ -4459,6 +4595,8 @@ static void handle_hpd_irq(void *param) {
> struct amdgpu_dm_connector *aconnector = (struct
> amdgpu_dm_connector *)param;
>
> + /* Cancel any pending work */
> + dm_cancel_delayed_hpd_work(aconnector);
> handle_hpd_irq_helper(aconnector, DETECT_REASON_HPD);
>
> }
> 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 7d37c1612131..9a66c9e2b78d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -136,6 +136,18 @@ struct dmub_hpd_work {
> struct amdgpu_device *adev;
> };
>
> +/**
> + * struct delayed_hpd_work - Handle delayed HPD (hot plug detection)
> +work
> + *
> + * @work: Base structure, kernel work data for the work event
> + * @aconn: Pointer to connector where the HPD event happened */ struct
> +delayed_hpd_work {
> + struct delayed_work work;
> + struct amdgpu_dm_connector *aconn;
> + enum dc_detect_reason reason;
> +};
> +
> /**
> * struct vblank_control_work - Work data for vblank control
> * @work: Kernel work data for the work event @@ -801,6 +813,10 @@
> struct amdgpu_dm_connector {
> /* number of modes generated from EDID at 'dc_sink' */
> int num_modes;
>
> + /* number of retries on hot plug detection */
> + int num_hpd_retries;
> + struct delayed_hpd_work *delayed_hpd_work;
> +
> /* The 'old' sink - before an HPD.
> * The 'current' sink is in dc_link->sink. */
> struct dc_sink *dc_sink;
> --
> 2.54.0
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 21/24] drm/amd/display: Retry link detection on hotplug
2026-06-05 16:10 ` Zuo, Jerry
@ 2026-06-05 18:26 ` Aurabindo Pillai
2026-06-05 20:49 ` Timur Kristóf
2026-06-08 18:31 ` Zuo, Jerry
2 siblings, 0 replies; 30+ messages in thread
From: Aurabindo Pillai @ 2026-06-05 18:26 UTC (permalink / raw)
To: Zuo, Jerry, amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry, Li, Sun peng (Leo), Li, Roman, Lin, Wayne,
Chung, ChiaHsuan (Tom), Wheeler, Daniel, Wu, Ray, LIPSKI, IVAN,
Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu, Timur Kristóf
On 6/5/26 12:10 PM, Zuo, Jerry wrote:
> AMD General
>
> Hi Timur:
>
> Please let me know whether you have validated the sequence by any SST and HDMI monitor. Basically it is to confirm the link retry workqueue is getting executed with hotplug and dpms use cases without introducing side effect. We've tested locally, but we don't see any link retry workqueue is getting executed by either SST or HDMI monitors. That makes us hard to validate the new error handling logic. It would be perfect that if you have done that at your local setup to confirm the new logic is regression-free for SST and HDMI.
>
> Apart from that, we find a regression in MST. MST has its own detection logic and should be separated from SST and HDMI.
>
> Regards,
> Jerry
>
Hi Timur,
Thanks for the patches, but unfortunately we're likely to drop this
patch and your other patch "drm/amd/display: Retry link detection on
resume and boot" due to regressions. Jerry will try to find a fix. When
its ready, we'll apply the patch along with the fix.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 21/24] drm/amd/display: Retry link detection on hotplug
2026-06-05 16:10 ` Zuo, Jerry
2026-06-05 18:26 ` Aurabindo Pillai
@ 2026-06-05 20:49 ` Timur Kristóf
2026-06-08 18:31 ` Zuo, Jerry
2 siblings, 0 replies; 30+ messages in thread
From: Timur Kristóf @ 2026-06-05 20:49 UTC (permalink / raw)
To: Pillai, Aurabindo, amd-gfx@lists.freedesktop.org, Zuo, Jerry
Cc: Wentland, Harry, Li, Sun peng (Leo), Pillai, Aurabindo, Li, Roman,
Lin, Wayne, Chung, ChiaHsuan (Tom), Wheeler, Daniel, Wu, Ray,
LIPSKI, IVAN, Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu
On Friday, June 5, 2026 6:10:28 PM Central European Summer Time Zuo, Jerry
wrote:
> AMD General
>
> Hi Timur:
>
> Please let me know whether you have validated the sequence by any SST
> and HDMI monitor. Basically it is to confirm the link retry workqueue is
> getting executed with hotplug and dpms use cases without introducing side
> effect. We've tested locally, but we don't see any link retry workqueue is
> getting executed by either SST or HDMI monitors. That makes us hard to
> validate the new error handling logic. It would be perfect that if you have
> done that at your local setup to confirm the new logic is regression-free
> for SST and HDMI.
Hello Jerry,
Yes, it worked for me last I tried, but I can double-check to make sure.
How did you try to test it?
> Apart from that, we find a regression in MST. MST has its own detection
> logic and should be separated from SST and HDMI.
Can you say what the regression is and how to reproduce it?
I'd like to look into it and fix it.
By the way, how do you test MST in general? On my machine, MST doesn't work at
with the DC display driver and is basically broken on every GPU generation
that I tried.
Thanks,
Timur
>
>
> > -----Original Message-----
> > From: Aurabindo Pillai <aurabindo.pillai@amd.com>
> > Sent: Thursday, June 4, 2026 10:52
> > To: amd-gfx@lists.freedesktop.org
> > Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo)
> > <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>; Li,
> > Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung,
> > ChiaHsuan (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry
> > <Jerry.Zuo@amd.com>; Wheeler, Daniel <Daniel.Wheeler@amd.com>; Wu,
> > Ray <Ray.Wu@amd.com>; LIPSKI, IVAN <IVAN.LIPSKI@amd.com>; Hung, Alex
> > <Alex.Hung@amd.com>; Lin, Ping Lei <PingLei.Lin@amd.com>; Chen, Chen-
> > Yu <Chen-Yu.Chen@amd.com>; Timur Kristóf <timur.kristof@gmail.com>
> > Subject: [PATCH 21/24] drm/amd/display: Retry link detection on hotplug
> >
> >
> >
> > From: Timur Kristóf <timur.kristof@gmail.com>
> >
> >
> >
> > When dc_link_detect_connection_type thinks that a display is connected,
> > but
dc_link_detect failed, enqueue delayed work to retry the link
> > detection again.>
> >
> >
> > Useful when eg. HPD pin is high but the display isn't ready and didn't
> > respond
to DDC.
> >
> >
> >
> > - The display is "slow to wake up", ie. DDC isn't ready,
> >
> > for example we couldn't read EDID. Can happen with any
> > connector type with certain "slow" displays.
> > Some displays may take up to 15~20 sec or more to wake up.
> >
> >
> >
> > - On hotplug, the HPD pin may make contact before the DDC pins,
> >
> > so we couldn't read the EDID. This most often happens with
> > DVI connectors, rarely with HDMI. It is not impossible but
> > extremely rare with other connector types.
> >
> >
> >
> > Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
> > Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
> > Reviewed-by: Alex Hung <alex.hung@amd.com>
> > ---
> >
> > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 138
> >
> > ++++++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> >
> > | 16 ++
> >
> > 2 files changed, 154 insertions(+)
> >
> >
> >
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index d1b1eb67d937..40295a5edbec 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -161,6 +161,17 @@ MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB);
> >
> > #define FIRMWARE_DCN_42B_DMUB "amdgpu/dcn_4_2_1_dmcub.bin"
> > MODULE_FIRMWARE(FIRMWARE_DCN_42B_DMUB);
> >
> >
> >
> > +/**
> > + * define AMDGPU_DM_HPD_MAX_NUM_RETRIES - maximum amount of
> > retries for
> > +hotplug detection */ #define AMDGPU_DM_HPD_MAX_NUM_RETRIES 5
> > +
> > +/**
> > + * define AMDGPU_DM_HPD_RETRY_DELAY_MSEC - millisecond delay
> > between
> > +hotplug detection retries */ #define
> > AMDGPU_DM_HPD_RETRY_DELAY_MSEC
> > +1500
> > +
> > +
> >
> > /**
> >
> > * DOC: overview
> > *
> >
> > @@ -959,6 +970,125 @@ static void dm_handle_hpd_work(struct
> > work_struct *work)
> >
> >
> >
> > }
> >
> >
> >
> > +/**
> > + * dm_handle_delayed_hpd_work() - Handle delayed HPD (hotplug
> > +detection)
> > + *
> > + * @w: Base work item structure
> > + *
> > + * Used for retrying HPD after a delay. Just calls the normal HPD
> > helper.
> > + */
> > +static void dm_handle_delayed_hpd_work(struct work_struct *work) {
> > + struct delayed_work *dw = container_of(work, struct delayed_work,
> > work);
> > + struct delayed_hpd_work *w = container_of(dw, struct
> > delayed_hpd_work, work);
> > + struct amdgpu_dm_connector *aconn = w->aconn;
> > + enum dc_detect_reason reason = w->reason;
> > +
> > + kfree(w);
> > + handle_hpd_irq_helper(aconn, reason);
> > +}
> > +
> > +/**
> > + * dm_cancel_delayed_hpd_work() - Cancel pending hotplug detection work
> > +for a connector
> > + *
> > + * @aconnector: Connector on which the HPD event occurred */ static
> > +void dm_cancel_delayed_hpd_work(struct amdgpu_dm_connector
> > *aconnector)
> > +{
> > + if (!aconnector || !aconnector->delayed_hpd_work)
> > + return;
> > +
> > + cancel_delayed_work(&aconnector->delayed_hpd_work->work);
> > + aconnector->delayed_hpd_work = NULL;
> > +}
> > +
> > +/**
> > + * dm_cancel_all_delayed_hpd_work() - Cancel all pending hotplug
> > +detection work on the device
> > + *
> > + * @dev: DRM device pointer
> > + */
> > +static void dm_cancel_all_delayed_hpd_work(struct drm_device *dev) {
> > + struct drm_connector *connector;
> > + struct drm_connector_list_iter iter;
> > +
> > + drm_connector_list_iter_begin(dev, &iter);
> > + drm_for_each_connector_iter(connector, &iter) {
> > + if (connector->connector_type ==
> > DRM_MODE_CONNECTOR_WRITEBACK)
> > + continue;
> > +
> > +
> >
> > dm_cancel_delayed_hpd_work(to_amdgpu_dm_connector(connecto
> >
> > r));
> > + }
> > + drm_connector_list_iter_end(&iter);
> > +}
> > +
> > +/**
> > + * dm_queue_delayed_hpd_work() - Enqueue delayed work to handle
> > hotplug
> > +detection
> > + *
> > + * @aconnector: Connector on which the HPD event occurred
> > + * @reason: Reason why we are attempting the HPD
> > + * @msecs: Millisecond delay after which the delayed work is going to
> > +happen
> > + *
> > + * When dc_link_detect_connection_type thinks that a display is
> > +connected,
> > + * but dc_link_detect failed, enqueue delayed work to retry the link
> > + * detection again.
> > + *
> > + * Useful when eg. HPD pin is high but the display isn't ready and
> > + * didn't respond to DDC.
> > + *
> > + * - On boot or suspend/resume, the display is "slow to wake up",
> > + * ie. DDC isn't ready, for example we couldn't read DP link caps or
> > EDID.
+ * Can happen to any connector with certain "slow" displays.
> > + *
> > + * - On hotplug, the HPD pin may make contact before the DDC pins,
> > + * so we couldn't read the EDID. Can happen to any connector but
> > + * most often to DVI and sometimes to HDMI (rarely to DP).
> > + *
> > + */
> > +static void dm_queue_delayed_hpd_work(struct amdgpu_dm_connector
> > *aconnector,
> > + const enum dc_detect_reason reason,
> > + const unsigned int msecs)
> > +{
> > + struct drm_device *dev = aconnector->base.dev;
> > + struct amdgpu_device *adev = drm_to_adev(dev);
> > + struct delayed_hpd_work *w;
> > +
> > + if (!aconnector || !aconnector->dc_link ||
> > + aconnector->dc_link->type == dc_connection_none)
> > + return;
> > +
> > + /* Don't retry polled connectors, the polling is going to detect it.
> > */
+ if (aconnector->base.polled != DRM_CONNECTOR_POLL_HPD)
> > + return;
> > +
> > + ++aconnector->num_hpd_retries;
> > +
> > + drm_dbg(dev, "Can't detect link on %s on try %d\n",
> > + aconnector->base.name, aconnector->num_hpd_retries);
> > +
> > + if (aconnector->num_hpd_retries >
> > AMDGPU_DM_HPD_MAX_NUM_RETRIES) {
> > + drm_warn(dev, "Too many retries on %s: %d, giving up\n",
> > + aconnector->base.name, aconnector-
> >
> > >num_hpd_retries);
> >
> > + aconnector->num_hpd_retries = 0;
> > + return;
> > + }
> > +
> > + w = kzalloc(sizeof(*w), GFP_ATOMIC);
> > +
> > + if (!w)
> > + return;
> > +
> > + INIT_DELAYED_WORK(&w->work, dm_handle_delayed_hpd_work);
> > + w->aconn = aconnector;
> > + w->reason = reason;
> > + aconnector->delayed_hpd_work = w;
> > +
> > + drm_warn(dev, "Enqueueing next retry on %s\n",
> > + aconnector->base.name);
> > + queue_delayed_work(adev->dm.delayed_hpd_wq, &w->work,
> > + msecs_to_jiffies(msecs));
> > +}
> > +
> >
> > static const char *dmub_notification_type_str(enum
> > dmub_notification_type
> >
> > e) {
> >
> > switch (e) {
> >
> > @@ -3249,6 +3379,7 @@ static int dm_hw_fini(struct amdgpu_ip_block
> > *ip_block) {
> >
> > struct amdgpu_device *adev = ip_block->adev;
> >
> >
> >
> > + dm_cancel_all_delayed_hpd_work(&adev->ddev);
> >
> > amdgpu_dm_hpd_fini(adev);
> >
> >
> >
> > amdgpu_dm_irq_fini(adev);
> >
> > @@ -3422,6 +3553,8 @@ static int dm_suspend(struct amdgpu_ip_block
> > *ip_block)
> >
> > struct amdgpu_device *adev = ip_block->adev;
> > struct amdgpu_display_manager *dm = &adev->dm;
> >
> >
> >
> > + dm_cancel_all_delayed_hpd_work(&adev->ddev);
> > +
> >
> > if (amdgpu_in_reset(adev)) {
> >
> > enum dc_status res;
> >
> >
> >
> > @@ -4451,6 +4584,9 @@ static void handle_hpd_irq_helper(struct
> > amdgpu_dm_connector *aconnector,
> >
> > if (aconnector->base.force ==
> >
> > DRM_FORCE_UNSPECIFIED ||
> >
> > reason == DETECT_REASON_HPDRX)
> >
> >
> >
> > drm_kms_helper_connector_hotplug_event(connector);
> >
> > + } else {
>
>
>
> We need to return here if aconnector->mst_mgr.mst_state is set.
>
>
>
> > + dm_queue_delayed_hpd_work(aconnector, reason,
> > +
> > AMDGPU_DM_HPD_RETRY_DELAY_MSEC);
> >
> > }
> >
> > }
> >
> > }
> >
> > @@ -4459,6 +4595,8 @@ static void handle_hpd_irq(void *param) {
> >
> > struct amdgpu_dm_connector *aconnector = (struct
> >
> > amdgpu_dm_connector *)param;
> >
> >
> >
> > + /* Cancel any pending work */
> > + dm_cancel_delayed_hpd_work(aconnector);
> >
> > handle_hpd_irq_helper(aconnector, DETECT_REASON_HPD);
> >
> >
> >
> > }
> >
> > 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 7d37c1612131..9a66c9e2b78d 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > @@ -136,6 +136,18 @@ struct dmub_hpd_work {
> >
> > struct amdgpu_device *adev;
> >
> > };
> >
> >
> >
> > +/**
> > + * struct delayed_hpd_work - Handle delayed HPD (hot plug detection)
> > +work
> > + *
> > + * @work: Base structure, kernel work data for the work event
> > + * @aconn: Pointer to connector where the HPD event happened */ struct
> > +delayed_hpd_work {
> > + struct delayed_work work;
> > + struct amdgpu_dm_connector *aconn;
> > + enum dc_detect_reason reason;
> > +};
> > +
> >
> > /**
> >
> > * struct vblank_control_work - Work data for vblank control
> > * @work: Kernel work data for the work event @@ -801,6 +813,10 @@
> >
> > struct amdgpu_dm_connector {
> >
> > /* number of modes generated from EDID at 'dc_sink' */
> > int num_modes;
> >
> >
> >
> > + /* number of retries on hot plug detection */
> > + int num_hpd_retries;
> > + struct delayed_hpd_work *delayed_hpd_work;
> > +
> >
> > /* The 'old' sink - before an HPD.
> >
> > * The 'current' sink is in dc_link->sink. */
> >
> > struct dc_sink *dc_sink;
> >
> > --
> > 2.54.0
>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [PATCH 00/24] DC Patches for 8 June 2026
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
` (23 preceding siblings ...)
2026-06-04 14:52 ` [PATCH 24/24] drm/amd/display: Promote DC to 3.2.385 Aurabindo Pillai
@ 2026-06-08 13:25 ` Wheeler, Daniel
24 siblings, 0 replies; 30+ messages in thread
From: Wheeler, Daniel @ 2026-06-08 13:25 UTC (permalink / raw)
To: Pillai, Aurabindo, amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry, Li, Sun peng (Leo), Pillai, Aurabindo, Li, Roman,
Lin, Wayne, Chung, ChiaHsuan (Tom), Zuo, Jerry, Wu, Ray,
LIPSKI, IVAN, Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu
Public
Hi all,
This week this patchset was tested on 4 systems, two dGPU and two APU based, and tested across multiple display and connection types. This week was also the last promotion test ran on Ubuntu 24.04. There won't be any testing this week as we had a holiday this past Monday, so the first test on Ubuntu 26.04 will begin next week.
APU
• Single Display eDP -> 1080p 60hz, 1920x1200 165hz, 3840x2400 60hz
• Single Display DP (SST DSC) -> 4k144hz, 4k240hz
• Multi display -> eDP + DP/HDMI/USB-C -> 1080p 60hz eDP + 4k 144hz, 4k 240hz (Includes USB-C to DP/HDMI adapters)
• Thunderbolt -> LG Ultrafine 5k
• MST DSC -> Cable Matters 101075 (DP to 3x DP) with 3x 4k60hz displays, HP Hook G2 with 2x 4k60hz displays
• USB 4 -> HP Hook G4, Lenovo Thunderbolt Dock, both with 2x 4k60hz DP and 1x 4k60hz HDMI displays
• SST PCON -> Club3D CAC-1085 + 1x 4k 144hz, FRL3, at a max resolution supported by the dongle of 4k 120hz YUV420 12bpc.
• MST PCON -> 1x 4k 144hz, FRL3, at a max resolution supported by the adapter of 4k 120hz RGB 8bpc.
DGPU
• Single Display DP (SST DSC) -> 4k144hz, 4k240hz
• Multiple Display DP -> 4k240hz + 4k144hz
• MST (Startech MST14DP123DP [DP to 3x DP] and 2x 4k 60hz displays)
• MST DSC (with Cable Matters 101075 [DP to 3x DP] with 3x 4k60hz displays)
The testing is a mix of automated and manual tests. Manual testing includes (but is not limited to)
• Changing display configurations and settings
• Video/Audio playback
• Benchmark testing
• Suspend/Resume testing
• Feature testing (Freesync, HDCP, etc.)
Automated testing includes (but is not limited to)
• Script testing (scripts to automate some of the manual checks)
• IGT testing
The testing is mainly tested on the following displays, but occasionally there are tests with other displays
• Samsung G8 Neo 4k240hz
• Samsung QN55QN95B 4k 120hz
• Acer XV322QKKV 4k144hz
• HP U27 4k Wireless 4k60hz
• LG 27UD58B 4k60hz
• LG 32UN650WA 4k60hz
• LG Ultrafine 5k 5k60hz
• AU Optronics B140HAN01.1 1080p 60hz eDP
• AU Optronics B160UAN01.J 1920x1200 165hz eDP
• Samsung ATNA60YV02-0 3840x2400 60Hz OLED eDP
The patchset consists of the amd-staging-drm-next branch (Head commit -> 75d5eab3acdc2496e0dba10ba3e7d8e96855755c -> drm/amd/ras: Remove redundant error log) with new patches added on top of it.
Tested on Ubuntu 26.04.4, on Wayland and X11, using Gnome.
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Thank you,
Dan Wheeler
Sr. Technologist | AMD
SW Display
------------------------------------------------------------------------------------------------------------------
1 Commerce Valley Dr E, Thornhill, ON L3T 7X6
amd.com
-----Original Message-----
From: Aurabindo Pillai <aurabindo.pillai@amd.com>
Sent: Thursday, June 4, 2026 10:52 AM
To: amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung, ChiaHsuan (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry <Jerry.Zuo@amd.com>; Wheeler, Daniel <Daniel.Wheeler@amd.com>; Wu, Ray <Ray.Wu@amd.com>; LIPSKI, IVAN <IVAN.LIPSKI@amd.com>; Hung, Alex <Alex.Hung@amd.com>; Lin, Ping Lei <PingLei.Lin@amd.com>; Chen, Chen-Yu <Chen-Yu.Chen@amd.com>
Subject: [PATCH 00/24] DC Patches for 8 June 2026
Summary:
* Display connectivity & HPD:
- Retry link detection on resume, boot, and hotplug
- Refactor HPD RX to use handle_hpd_irq_helper with detect reason
- Always create delayed HPD work queue
- Restore periodic detection for DCN35
* DCN42B support:
- Fix DCN42B version detection
- Add DCN42B to dml21_translation_helper
* KUnit testing infrastructure:
- Add KUnit tests for amdgpu_dm_pp_smu, amdgpu_dm_mst_types,
and writeback connector
- Extract HDCP and DPRX CRC transition helpers for KUnit
- Export symbols for KUnit test modules
- Enable warnings as errors for KUnit tests
* Fixes & cleanups:
- Fix compressed buffer config routine waiting time
- Fix incorrect logic in CRC source handling
- Fix writeback format loop and variable init
- Fix max dispclk_khz/dppclk_khz double 1000
- Remove duplicate pp_rn_set_wm_ranges
- Remove dead code in dm_dp_mst_get_modes
- Remove redundant code in amdgpu_dm_replay
- Skip PHY SSC reduction on some 8K panels
- Temp disable repeater FGCG as workaround
- Deprecate DMUB register offload functionality
- TEST_HARNESS FSN could be 0
* Firmware:
- DMUB FW promotion to 0.1.62.0
---
Alex Hung (11):
drm/amd/display: Fix writeback format loop and variable init
drm/amd/display: Add KUnit tests for writeback connector
drm/amd/display: remove redundant code in amdgpu_dm_replay
drm/amd/display: Enable warnings as errors for KUnit tests
drm/amd/display: Remove dead code in dm_dp_mst_get_modes
drm/amd/display: Add KUnit tests for amdgpu_dm_mst_types
drm/amd/display: Fix incorrect logic in CRC source handling
drm/amd/display: Extract DPRX CRC transition helpers for KUnit testing
drm/amd/display: Extract HDCP testable helpers for KUnit
drm/amd/display: Remove duplicate pp_rn_set_wm_ranges
drm/amd/display: Add KUnit tests for amdgpu_dm_pp_smu
Antonio Quartulli (1):
drm/amd/display: fix compressed buffer config routine waiting time
Austin Zheng (1):
drm/amd/display: Deprecate DMUB register offload functionality
Charlene Liu (1):
drm/amd/display: fix max dispclk_khz/dppclk_khz double 1000
ChunTao Tso (1):
drm/amd/display: TEST_HARNESS FSN could be 0
Ivan Lipski (1):
drm/amd/display: Restore periodic detection for DCN35
Ovidiu Bunea (1):
drm/amd/display: Temp disable repeater FGCG as workaround
Roman Li (1):
drm/amd/display: Skip PHY SSC reduction on some 8K panels
Taimur Hassan (1):
drm/amd/display: Promote DC to 3.2.385
Timur Kristóf (5):
drm/amd/display: Add detect reason to handle_hpd_irq_helper
drm/amd/display: Use handle_hpd_irq_helper for HPD RX
drm/amd/display: Always create delayed HPD work queue
drm/amd/display: Retry link detection on hotplug
drm/amd/display: Retry link detection on resume and boot
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 224 ++++++++---- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 16 + .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 100 ++++--
.../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 6 +
.../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 115 ++++--
.../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 12 +
.../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 +-
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 25 +-
.../display/amdgpu_dm/amdgpu_dm_mst_types.h | 6 +
.../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 21 +- .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h | 16 +
.../amd/display/amdgpu_dm/amdgpu_dm_replay.c | 7 +-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c | 15 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_wb.h | 13 +
.../amd/display/amdgpu_dm/tests/.kunitconfig | 3 +
.../drm/amd/display/amdgpu_dm/tests/Makefile | 4 +
.../amdgpu_dm/tests/amdgpu_dm_crc_test.c | 122 +++++++
.../amdgpu_dm/tests/amdgpu_dm_hdcp_test.c | 297 +++++++++++++++-
.../tests/amdgpu_dm_mst_types_test.c | 124 +++++++
.../amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c | 241 +++++++++++++
.../amdgpu_dm/tests/amdgpu_dm_wb_test.c | 336 ++++++++++++++++++
.../display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 -
.../dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 2 -
.../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 2 +
drivers/gpu/drm/amd/display/dc/dc.h | 6 +-
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 12 -
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 9 -
drivers/gpu/drm/amd/display/dc/dc_helper.c | 226 ------------
.../amd/display/dc/dccg/dcn42/dcn42_dccg.c | 6 +-
drivers/gpu/drm/amd/display/dc/dm_services.h | 4 -
.../dc/dml2_0/dml21/dml21_wrapper_fpu.c | 8 +-
.../amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c | 5 -
.../display/dc/hubbub/dcn31/dcn31_hubbub.c | 8 +-
.../amd/display/dc/hubp/dcn42/dcn42_hubp.c | 6 +
.../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 3 -
.../amd/display/dc/hwss/dcn42/dcn42_hwseq.c | 9 +-
.../gpu/drm/amd/display/dc/inc/reg_helper.h | 19 -
.../drm/amd/display/dc/mpc/dcn20/dcn20_mpc.c | 4 -
.../amd/display/dc/optc/dcn10/dcn10_optc.c | 5 -
.../amd/display/dc/optc/dcn20/dcn20_optc.c | 5 -
.../amd/display/dc/optc/dcn31/dcn31_optc.c | 5 -
.../amd/display/dc/optc/dcn314/dcn314_optc.c | 5 -
.../amd/display/dc/optc/dcn32/dcn32_optc.c | 5 -
.../amd/display/dc/optc/dcn35/dcn35_optc.c | 5 -
.../amd/display/dc/optc/dcn401/dcn401_optc.c | 5 -
.../dc/resource/dcn35/dcn35_resource.c | 1 -
.../dc/resource/dcn351/dcn351_resource.c | 1 -
.../dc/resource/dcn36/dcn36_resource.c | 1 -
.../dc/resource/dcn42/dcn42_resource.c | 1 +
.../amd/display/modules/power/power_replay.c | 9 +-
50 files changed, 1576 insertions(+), 519 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.h
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_pp_smu_test.c
create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
--
2.54.0
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [PATCH 21/24] drm/amd/display: Retry link detection on hotplug
2026-06-05 16:10 ` Zuo, Jerry
2026-06-05 18:26 ` Aurabindo Pillai
2026-06-05 20:49 ` Timur Kristóf
@ 2026-06-08 18:31 ` Zuo, Jerry
2 siblings, 0 replies; 30+ messages in thread
From: Zuo, Jerry @ 2026-06-08 18:31 UTC (permalink / raw)
To: Timur Kristóf, amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry, Li, Sun peng (Leo), Pillai, Aurabindo, Li, Roman,
Lin, Wayne, Chung, ChiaHsuan (Tom), Wheeler, Daniel, Wu, Ray,
LIPSKI, IVAN, Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu,
Timur Kristóf
AMD General
Hi Timur:
The new link detection delay workqueue causes hard hang on Dell 6K DP2 monitor after a couple of hotplug. Please refer to below dmesg as reference.
[ 182.455489] watchdog: CPU1: Watchdog detected hard LOCKUP on cpu 1
[ 182.455490] Modules linked in: snd_seq_dummy snd_hrtimer qrtr intel_rapl_msr amd_atl intel_rapl_common binfmt_misc edac_mce_amd kvm_amd nls_iso8859_1 snd_hda_codec_atihdmi snd_hda_codec_hdmi kvm amdgpu snd_hda_intel rapl eeepc_wmi amdxcp snd_hda_codec asus_wmi drm_panel_backlight_quirks sparse_keymap platform_profile wmi_bmof snd_usb_audio snd_usbmidi_lib snd_hda_core gpu_sched drm_buddy mc snd_intel_dspcfg drm_ttm_helper snd_intel_sdw_acpi ttm drm_exec snd_seq_midi snd_seq_midi_event drm_suballoc_helper snd_hwdep drm_client_lib snd_pcm snd_rawmidi drm_display_helper i2c_piix4 k10temp i2c_smbus snd_seq drm_kms_helper r8169 snd_seq_device cec snd_timer snd rc_core i2c_algo_bit soundcore realtek input_leds joydev gpio_amdpt gpio_generic acpi_pad mac_hid sch_fq_codel drm efi_pstore nfnetlink hid_generic ucsi_acpi typec_ucsi typec usbhid hid ghash_clmulni_intel ccp ahci libahci video thunderbolt wmi parport_pc lp ppdev msr parport dmi_sysfs autofs4 aesni_intel
[ 182.455511] CPU: 1 UID: 0 PID: 262 Comm: kworker/1:1H Kdump: loaded Not tainted 6.19.0-promotion-june2-patchy3+ #319 PREEMPT(voluntary)
[ 182.455513] Hardware name: ASUS System Product Name/ROG STRIX X870E-E GAMING WIFI, BIOS 2202 04/09/2026
[ 182.455514] Workqueue: events_highpri dm_irq_work_func [amdgpu]
[ 182.455691] RIP: 0010:native_queued_spin_lock_slowpath+0x213/0x2c0
[ 182.455695] Code: 8d 46 01 41 c1 e5 10 c1 e0 12 41 09 c5 44 89 e8 c1 e8 10 66 87 43 02 89 c2 c1 e2 10 81 fa ff ff 00 00 77 51 31 d2 eb 02 f3 90 <8b> 03 66 85 c0 75 f7 44 39 e8 0f 84 85 00 00 00 c6 03 01 48 85 d2
[ 182.455696] RSP: 0018:ffffd17bc08e3ce0 EFLAGS: 00000006
[ 182.455697] RAX: 0000000000081000 RBX: ffffffff8d4176ff RCX: 0000000000000000
[ 182.455698] RDX: 0000000000000000 RSI: ffffffff8ca9f20c RDI: ffffffff8ca88b37
[ 182.455698] RBP: ffffd17bc08e3d00 R08: 8080808080808080 R09: ffff8a5c8186b100
[ 182.455698] R10: ffff8a5c80052ec0 R11: fefefefefefefeff R12: ffff8a63ac2731c0
[ 182.455699] R13: 0000000000080000 R14: 0000000000000001 R15: 0000000000000000
[ 182.455699] FS: 0000000000000000(0000) GS:ffff8a641ee49000(0000) knlGS:0000000000000000
[ 182.455700] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 182.455700] CR2: 0000562bd6ca9000 CR3: 0000000200436000 CR4: 0000000000750ef0
[ 182.455701] PKRU: 55555554
[ 182.455701] Call Trace:
[ 182.455701] <TASK>
[ 182.455702] _raw_spin_lock_irqsave+0x4b/0x60
[ 182.455704] lock_timer_base+0x73/0xa0
[ 182.455707] timer_delete+0x36/0x80
[ 182.455708] try_to_grab_pending+0x121/0x1d0
[ 182.455710] __cancel_work+0x3b/0x100
[ 182.455711] ? finish_task_switch.isra.0+0x92/0x280
[ 182.455713] cancel_delayed_work+0x13/0x20
[ 182.455714] handle_hpd_irq+0x23/0x50 [amdgpu]
[ 182.455859] dm_irq_work_func+0x19/0x20 [amdgpu]
[ 182.455991] process_one_work+0x18f/0x3d0
[ 182.455992] worker_thread+0x2cf/0x410
[ 182.455993] ? _raw_spin_unlock_irqrestore+0x27/0x50
[ 182.455994] ? __pfx_worker_thread+0x10/0x10
[ 182.455995] kthread+0x11c/0x230
[ 182.455997] ? _raw_spin_unlock_irq+0x1f/0x40
[ 182.455998] ? __pfx_kthread+0x10/0x10
[ 182.455999] ret_from_fork+0x195/0x210
[ 182.456001] ? __pfx_kthread+0x10/0x10
[ 182.456002] ret_from_fork_asm+0x1a/0x30
[ 182.456004] </TASK>
[ 185.660573] amdgpu 0000:03:00.0: [drm] *ERROR* [CRTC:423:crtc-0] flip_done timed out
[ 185.660587] amdgpu 0000:03:00.0: [drm:drm_atomic_state_default_clear [drm]] Clearing atomic state 00000000f6b354ad
[ 185.660622] amdgpu 0000:03:00.0: [drm:__drm_atomic_state_free [drm]] Freeing atomic state 00000000f6b354ad
[ 217.116563] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
[ 217.116569] rcu: 1-...0: (9 GPs behind) idle=af8c/1/0x4000000000000000 softirq=14209/14209 fqs=5572
[ 217.116575] rcu: (detected by 13, t=15002 jiffies, g=21165, q=9426 ncpus=16)
[ 217.116578] Sending NMI from CPU 13 to CPUs 1:
[ 217.116580] NMI backtrace for cpu 1
[ 217.116581] CPU: 1 UID: 0 PID: 262 Comm: kworker/1:1H Kdump: loaded Not tainted 6.19.0-promotion-june2-patchy3+ #319 PREEMPT(voluntary)
[ 217.116582] Hardware name: ASUS System Product Name/ROG STRIX X870E-E GAMING WIFI, BIOS 2202 04/09/2026
[ 217.116582] Workqueue: events_highpri dm_irq_work_func [amdgpu]
[ 217.116721] RIP: 0010:native_queued_spin_lock_slowpath+0x213/0x2c0
[ 217.116723] Code: 8d 46 01 41 c1 e5 10 c1 e0 12 41 09 c5 44 89 e8 c1 e8 10 66 87 43 02 89 c2 c1 e2 10 81 fa ff ff 00 00 77 51 31 d2 eb 02 f3 90 <8b> 03 66 85 c0 75 f7 44 39 e8 0f 84 85 00 00 00 c6 03 01 48 85 d2
[ 217.116723] RSP: 0018:ffffd17bc08e3ce0 EFLAGS: 00000006
[ 217.116724] RAX: 0000000000081000 RBX: ffffffff8d4176ff RCX: 0000000000000000
[ 217.116724] RDX: 0000000000000000 RSI: ffffffff8ca9f20c RDI: ffffffff8ca88b37
[ 217.116725] RBP: ffffd17bc08e3d00 R08: 8080808080808080 R09: ffff8a5c8186b100
[ 217.116725] R10: ffff8a5c80052ec0 R11: fefefefefefefeff R12: ffff8a63ac2731c0
[ 217.116725] R13: 0000000000080000 R14: 0000000000000001 R15: 0000000000000000
[ 217.116725] FS: 0000000000000000(0000) GS:ffff8a641ee49000(0000) knlGS:0000000000000000
[ 217.116726] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 217.116726] CR2: 0000562bd6ca9000 CR3: 0000000200436000 CR4: 0000000000750ef0
[ 217.116727] PKRU: 55555554
[ 217.116727] Call Trace:
[ 217.116727] <TASK>
[ 217.116727] _raw_spin_lock_irqsave+0x4b/0x60
[ 217.116728] lock_timer_base+0x73/0xa0
[ 217.116730] timer_delete+0x36/0x80
[ 217.116730] try_to_grab_pending+0x121/0x1d0
[ 217.116731] __cancel_work+0x3b/0x100
[ 217.116732] ? finish_task_switch.isra.0+0x92/0x280
[ 217.116733] cancel_delayed_work+0x13/0x20
[ 217.116734] handle_hpd_irq+0x23/0x50 [amdgpu]
[ 217.116866] dm_irq_work_func+0x19/0x20 [amdgpu]
[ 217.116992] process_one_work+0x18f/0x3d0
[ 217.116993] worker_thread+0x2cf/0x410
[ 217.116994] ? _raw_spin_unlock_irqrestore+0x27/0x50
[ 217.116995] ? __pfx_worker_thread+0x10/0x10
[ 217.116996] kthread+0x11c/0x230
[ 217.116997] ? _raw_spin_unlock_irq+0x1f/0x40
[ 217.116998] ? __pfx_kthread+0x10/0x10
[ 217.116999] ret_from_fork+0x195/0x210
[ 217.117000] ? __pfx_kthread+0x10/0x10
[ 217.117001] ret_from_fork_asm+0x1a/0x30
[ 217.117002] </TASK>
[ 244.249406] watchdog: BUG: soft lockup - CPU#3 stuck for 22s! [kworker/3:1:161]
Regards,
Jerry
> -----Original Message-----
> From: Zuo, Jerry
> Sent: Friday, June 5, 2026 12:10
> To: Aurabindo Pillai <aurabindo.pillai@amd.com>; amd-
> gfx@lists.freedesktop.org
> Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo)
> <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>; Li,
> Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung,
> ChiaHsuan (Tom) <ChiaHsuan.Chung@amd.com>; Wheeler, Daniel
> <Daniel.Wheeler@amd.com>; Wu, Ray <Ray.Wu@amd.com>; LIPSKI, IVAN
> <IVAN.LIPSKI@amd.com>; Hung, Alex <Alex.Hung@amd.com>; Lin, Ping Lei
> <PingLei.Lin@amd.com>; Chen, Chen-Yu <Chen-Yu.Chen@amd.com>; Timur
> Kristóf <timur.kristof@gmail.com>
> Subject: RE: [PATCH 21/24] drm/amd/display: Retry link detection on hotplug
>
> Hi Timur:
>
> Please let me know whether you have validated the sequence by any SST
> and HDMI monitor. Basically it is to confirm the link retry workqueue is
> getting executed with hotplug and dpms use cases without introducing side
> effect. We've tested locally, but we don't see any link retry workqueue is
> getting executed by either SST or HDMI monitors. That makes us hard to
> validate the new error handling logic. It would be perfect that if you have
> done that at your local setup to confirm the new logic is regression-free for
> SST and HDMI.
>
> Apart from that, we find a regression in MST. MST has its own detection
> logic and should be separated from SST and HDMI.
>
> Regards,
> Jerry
>
> > -----Original Message-----
> > From: Aurabindo Pillai <aurabindo.pillai@amd.com>
> > Sent: Thursday, June 4, 2026 10:52
> > To: amd-gfx@lists.freedesktop.org
> > Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo)
> > <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>;
> > Li, Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>;
> Chung,
> > ChiaHsuan (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry
> > <Jerry.Zuo@amd.com>; Wheeler, Daniel <Daniel.Wheeler@amd.com>; Wu,
> Ray
> > <Ray.Wu@amd.com>; LIPSKI, IVAN <IVAN.LIPSKI@amd.com>; Hung, Alex
> > <Alex.Hung@amd.com>; Lin, Ping Lei <PingLei.Lin@amd.com>; Chen, Chen-
> > Yu <Chen-Yu.Chen@amd.com>; Timur Kristóf <timur.kristof@gmail.com>
> > Subject: [PATCH 21/24] drm/amd/display: Retry link detection on
> > hotplug
> >
> > From: Timur Kristóf <timur.kristof@gmail.com>
> >
> > When dc_link_detect_connection_type thinks that a display is
> > connected, but dc_link_detect failed, enqueue delayed work to retry the
> link detection again.
> >
> > Useful when eg. HPD pin is high but the display isn't ready and didn't
> > respond to DDC.
> >
> > - The display is "slow to wake up", ie. DDC isn't ready,
> > for example we couldn't read EDID. Can happen with any
> > connector type with certain "slow" displays.
> > Some displays may take up to 15~20 sec or more to wake up.
> >
> > - On hotplug, the HPD pin may make contact before the DDC pins,
> > so we couldn't read the EDID. This most often happens with
> > DVI connectors, rarely with HDMI. It is not impossible but
> > extremely rare with other connector types.
> >
> > Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
> > Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
> > Reviewed-by: Alex Hung <alex.hung@amd.com>
> > ---
> > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 138
> >
> ++++++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > | 16 ++
> > 2 files changed, 154 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index d1b1eb67d937..40295a5edbec 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -161,6 +161,17 @@
> MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB);
> > #define FIRMWARE_DCN_42B_DMUB "amdgpu/dcn_4_2_1_dmcub.bin"
> > MODULE_FIRMWARE(FIRMWARE_DCN_42B_DMUB);
> >
> > +/**
> > + * define AMDGPU_DM_HPD_MAX_NUM_RETRIES - maximum amount of
> > retries for
> > +hotplug detection */ #define AMDGPU_DM_HPD_MAX_NUM_RETRIES 5
> > +
> > +/**
> > + * define AMDGPU_DM_HPD_RETRY_DELAY_MSEC - millisecond delay
> > between
> > +hotplug detection retries */ #define
> > AMDGPU_DM_HPD_RETRY_DELAY_MSEC
> > +1500
> > +
> > +
> > /**
> > * DOC: overview
> > *
> > @@ -959,6 +970,125 @@ static void dm_handle_hpd_work(struct
> > work_struct *work)
> >
> > }
> >
> > +/**
> > + * dm_handle_delayed_hpd_work() - Handle delayed HPD (hotplug
> > +detection)
> > + *
> > + * @w: Base work item structure
> > + *
> > + * Used for retrying HPD after a delay. Just calls the normal HPD helper.
> > + */
> > +static void dm_handle_delayed_hpd_work(struct work_struct *work) {
> > + struct delayed_work *dw = container_of(work, struct delayed_work,
> > work);
> > + struct delayed_hpd_work *w = container_of(dw, struct
> > delayed_hpd_work, work);
> > + struct amdgpu_dm_connector *aconn = w->aconn;
> > + enum dc_detect_reason reason = w->reason;
> > +
> > + kfree(w);
> > + handle_hpd_irq_helper(aconn, reason); }
> > +
> > +/**
> > + * dm_cancel_delayed_hpd_work() - Cancel pending hotplug detection
> > +work for a connector
> > + *
> > + * @aconnector: Connector on which the HPD event occurred */ static
> > +void dm_cancel_delayed_hpd_work(struct amdgpu_dm_connector
> > *aconnector)
> > +{
> > + if (!aconnector || !aconnector->delayed_hpd_work)
> > + return;
> > +
> > + cancel_delayed_work(&aconnector->delayed_hpd_work->work);
> > + aconnector->delayed_hpd_work = NULL; }
> > +
> > +/**
> > + * dm_cancel_all_delayed_hpd_work() - Cancel all pending hotplug
> > +detection work on the device
> > + *
> > + * @dev: DRM device pointer
> > + */
> > +static void dm_cancel_all_delayed_hpd_work(struct drm_device *dev) {
> > + struct drm_connector *connector;
> > + struct drm_connector_list_iter iter;
> > +
> > + drm_connector_list_iter_begin(dev, &iter);
> > + drm_for_each_connector_iter(connector, &iter) {
> > + if (connector->connector_type ==
> > DRM_MODE_CONNECTOR_WRITEBACK)
> > + continue;
> > +
> > +
> > dm_cancel_delayed_hpd_work(to_amdgpu_dm_connector(connecto
> > r));
> > + }
> > + drm_connector_list_iter_end(&iter);
> > +}
> > +
> > +/**
> > + * dm_queue_delayed_hpd_work() - Enqueue delayed work to handle
> > hotplug
> > +detection
> > + *
> > + * @aconnector: Connector on which the HPD event occurred
> > + * @reason: Reason why we are attempting the HPD
> > + * @msecs: Millisecond delay after which the delayed work is going to
> > +happen
> > + *
> > + * When dc_link_detect_connection_type thinks that a display is
> > +connected,
> > + * but dc_link_detect failed, enqueue delayed work to retry the link
> > + * detection again.
> > + *
> > + * Useful when eg. HPD pin is high but the display isn't ready and
> > + * didn't respond to DDC.
> > + *
> > + * - On boot or suspend/resume, the display is "slow to wake up",
> > + * ie. DDC isn't ready, for example we couldn't read DP link caps or EDID.
> > + * Can happen to any connector with certain "slow" displays.
> > + *
> > + * - On hotplug, the HPD pin may make contact before the DDC pins,
> > + * so we couldn't read the EDID. Can happen to any connector but
> > + * most often to DVI and sometimes to HDMI (rarely to DP).
> > + *
> > + */
> > +static void dm_queue_delayed_hpd_work(struct amdgpu_dm_connector
> > *aconnector,
> > + const enum dc_detect_reason reason,
> > + const unsigned int msecs)
> > +{
> > + struct drm_device *dev = aconnector->base.dev;
> > + struct amdgpu_device *adev = drm_to_adev(dev);
> > + struct delayed_hpd_work *w;
> > +
> > + if (!aconnector || !aconnector->dc_link ||
> > + aconnector->dc_link->type == dc_connection_none)
> > + return;
> > +
> > + /* Don't retry polled connectors, the polling is going to detect it. */
> > + if (aconnector->base.polled != DRM_CONNECTOR_POLL_HPD)
> > + return;
> > +
> > + ++aconnector->num_hpd_retries;
> > +
> > + drm_dbg(dev, "Can't detect link on %s on try %d\n",
> > + aconnector->base.name, aconnector->num_hpd_retries);
> > +
> > + if (aconnector->num_hpd_retries >
> > AMDGPU_DM_HPD_MAX_NUM_RETRIES) {
> > + drm_warn(dev, "Too many retries on %s: %d, giving up\n",
> > + aconnector->base.name, aconnector-
> > >num_hpd_retries);
> > + aconnector->num_hpd_retries = 0;
> > + return;
> > + }
> > +
> > + w = kzalloc(sizeof(*w), GFP_ATOMIC);
> > +
> > + if (!w)
> > + return;
> > +
> > + INIT_DELAYED_WORK(&w->work, dm_handle_delayed_hpd_work);
> > + w->aconn = aconnector;
> > + w->reason = reason;
> > + aconnector->delayed_hpd_work = w;
> > +
> > + drm_warn(dev, "Enqueueing next retry on %s\n",
> > + aconnector->base.name);
> > + queue_delayed_work(adev->dm.delayed_hpd_wq, &w->work,
> > + msecs_to_jiffies(msecs));
> > +}
> > +
> > static const char *dmub_notification_type_str(enum
> > dmub_notification_type
> > e) {
> > switch (e) {
> > @@ -3249,6 +3379,7 @@ static int dm_hw_fini(struct amdgpu_ip_block
> > *ip_block) {
> > struct amdgpu_device *adev = ip_block->adev;
> >
> > + dm_cancel_all_delayed_hpd_work(&adev->ddev);
> > amdgpu_dm_hpd_fini(adev);
> >
> > amdgpu_dm_irq_fini(adev);
> > @@ -3422,6 +3553,8 @@ static int dm_suspend(struct amdgpu_ip_block
> > *ip_block)
> > struct amdgpu_device *adev = ip_block->adev;
> > struct amdgpu_display_manager *dm = &adev->dm;
> >
> > + dm_cancel_all_delayed_hpd_work(&adev->ddev);
> > +
> > if (amdgpu_in_reset(adev)) {
> > enum dc_status res;
> >
> > @@ -4451,6 +4584,9 @@ static void handle_hpd_irq_helper(struct
> > amdgpu_dm_connector *aconnector,
> > if (aconnector->base.force ==
> > DRM_FORCE_UNSPECIFIED ||
> > reason == DETECT_REASON_HPDRX)
> >
> > drm_kms_helper_connector_hotplug_event(connector);
> > + } else {
>
>
> We need to return here if aconnector->mst_mgr.mst_state is set.
>
>
> > + dm_queue_delayed_hpd_work(aconnector, reason,
> > +
> > AMDGPU_DM_HPD_RETRY_DELAY_MSEC);
> > }
> > }
> > }
> > @@ -4459,6 +4595,8 @@ static void handle_hpd_irq(void *param) {
> > struct amdgpu_dm_connector *aconnector = (struct
> amdgpu_dm_connector
> > *)param;
> >
> > + /* Cancel any pending work */
> > + dm_cancel_delayed_hpd_work(aconnector);
> > handle_hpd_irq_helper(aconnector, DETECT_REASON_HPD);
> >
> > }
> > 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 7d37c1612131..9a66c9e2b78d 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> > @@ -136,6 +136,18 @@ struct dmub_hpd_work {
> > struct amdgpu_device *adev;
> > };
> >
> > +/**
> > + * struct delayed_hpd_work - Handle delayed HPD (hot plug detection)
> > +work
> > + *
> > + * @work: Base structure, kernel work data for the work event
> > + * @aconn: Pointer to connector where the HPD event happened */
> > +struct delayed_hpd_work {
> > + struct delayed_work work;
> > + struct amdgpu_dm_connector *aconn;
> > + enum dc_detect_reason reason;
> > +};
> > +
> > /**
> > * struct vblank_control_work - Work data for vblank control
> > * @work: Kernel work data for the work event @@ -801,6 +813,10 @@
> > struct amdgpu_dm_connector {
> > /* number of modes generated from EDID at 'dc_sink' */
> > int num_modes;
> >
> > + /* number of retries on hot plug detection */
> > + int num_hpd_retries;
> > + struct delayed_hpd_work *delayed_hpd_work;
> > +
> > /* The 'old' sink - before an HPD.
> > * The 'current' sink is in dc_link->sink. */
> > struct dc_sink *dc_sink;
> > --
> > 2.54.0
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2026-06-08 18:31 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-04 14:51 [PATCH 00/24] DC Patches for 8 June 2026 Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 01/24] drm/amd/display: Skip PHY SSC reduction on some 8K panels Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 02/24] drm/amd/display: TEST_HARNESS FSN could be 0 Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 03/24] drm/amd/display: Deprecate DMUB register offload functionality Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 04/24] drm/amd/display: Temp disable repeater FGCG as workaround Aurabindo Pillai
2026-06-04 14:51 ` [PATCH 05/24] drm/amd/display: Fix writeback format loop and variable init Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 06/24] drm/amd/display: Add KUnit tests for writeback connector Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 07/24] drm/amd/display: fix max dispclk_khz/dppclk_khz double 1000 Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 08/24] drm/amd/display: remove redundant code in amdgpu_dm_replay Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 09/24] drm/amd/display: Enable warnings as errors for KUnit tests Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 10/24] drm/amd/display: Remove dead code in dm_dp_mst_get_modes Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 11/24] drm/amd/display: Add KUnit tests for amdgpu_dm_mst_types Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 12/24] drm/amd/display: Fix incorrect logic in CRC source handling Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 13/24] drm/amd/display: Extract DPRX CRC transition helpers for KUnit testing Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 14/24] drm/amd/display: Extract HDCP testable helpers for KUnit Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 15/24] drm/amd/display: Restore periodic detection for DCN35 Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 16/24] drm/amd/display: Remove duplicate pp_rn_set_wm_ranges Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 17/24] drm/amd/display: Add KUnit tests for amdgpu_dm_pp_smu Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 18/24] drm/amd/display: Add detect reason to handle_hpd_irq_helper Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 19/24] drm/amd/display: Use handle_hpd_irq_helper for HPD RX Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 20/24] drm/amd/display: Always create delayed HPD work queue Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 21/24] drm/amd/display: Retry link detection on hotplug Aurabindo Pillai
2026-06-05 16:10 ` Zuo, Jerry
2026-06-05 18:26 ` Aurabindo Pillai
2026-06-05 20:49 ` Timur Kristóf
2026-06-08 18:31 ` Zuo, Jerry
2026-06-04 14:52 ` [PATCH 22/24] drm/amd/display: Retry link detection on resume and boot Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 23/24] drm/amd/display: fix compressed buffer config routine waiting time Aurabindo Pillai
2026-06-04 14:52 ` [PATCH 24/24] drm/amd/display: Promote DC to 3.2.385 Aurabindo Pillai
2026-06-08 13:25 ` [PATCH 00/24] DC Patches for 8 June 2026 Wheeler, Daniel
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.