]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: Adjust PHY FSM transition to TX_EN-to-PLL_ON for TMDS on DCN35
authorNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Wed, 17 Dec 2025 18:21:59 +0000 (13:21 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Sat, 10 Jan 2026 19:21:53 +0000 (14:21 -0500)
[Why]
A backport of the change made for DCN401 that addresses an issue where
we turn off the PHY PLL when disabling TMDS output, which causes the
OTG to remain stuck.

The OTG being stuck can lead to a hang in the DCHVM's ability to ACK
invalidations when it thinks the HUBP is still on but it's not receiving
global sync.

The transition to PLL_ON needs to be atomic as there's no guarantee
that the thread isn't pre-empted or is able to complete before the
IOMMU watchdog times out.

[How]
Backport the implementation from dcn401 back to dcn35.

There's a functional difference in when the eDP output is disabled in
dcn401 code so we don't want to utilize it directly.

Reviewed-by: Yihan Zhu <yihan.zhu@amd.com>
Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Matthew Stewart <matthew.stewart2@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c

index 1271bf55dac3bf40e83a8c954a1087ffa5ed7e49..2675d7dca5864c1ba2d013ab1e3c2f8711ebadb9 100644 (file)
@@ -1727,3 +1727,55 @@ void dcn35_program_cursor_offload_now(struct dc *dc, const struct pipe_ctx *pipe
 {
        dc_dmub_srv_program_cursor_now(dc, pipe);
 }
+
+static void disable_link_output_symclk_on_tx_off(struct dc_link *link, enum dp_link_encoding link_encoding)
+{
+       struct dc *dc = link->ctx->dc;
+       struct pipe_ctx *pipe_ctx = NULL;
+       uint8_t i;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) {
+                       pipe_ctx->clock_source->funcs->program_pix_clk(
+                                       pipe_ctx->clock_source,
+                                       &pipe_ctx->stream_res.pix_clk_params,
+                                       link_encoding,
+                                       &pipe_ctx->pll_settings);
+                       break;
+               }
+       }
+}
+
+void dcn35_disable_link_output(struct dc_link *link,
+               const struct link_resource *link_res,
+               enum signal_type signal)
+{
+       struct dc *dc = link->ctx->dc;
+       const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
+       struct dmcu *dmcu = dc->res_pool->dmcu;
+
+       if (signal == SIGNAL_TYPE_EDP &&
+                       link->dc->hwss.edp_backlight_control &&
+                       !link->skip_implict_edp_power_control)
+               link->dc->hwss.edp_backlight_control(link, false);
+       else if (dmcu != NULL && dmcu->funcs->lock_phy)
+               dmcu->funcs->lock_phy(dmcu);
+
+       if (dc_is_tmds_signal(signal) && link->phy_state.symclk_ref_cnts.otg > 0) {
+               disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING);
+               link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
+       } else {
+               link_hwss->disable_link_output(link, link_res, signal);
+               link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+       }
+       /*
+        * Add the logic to extract BOTH power up and power down sequences
+        * from enable/disable link output and only call edp panel control
+        * in enable_link_dp and disable_link_dp once.
+        */
+       if (dmcu != NULL && dmcu->funcs->unlock_phy)
+               dmcu->funcs->unlock_phy(dmcu);
+
+       dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
+}
index 1ff41dba556c035de9349d07a5d578e1d17fdd78..e3459546a908a12ce7772f151a5136c3cb56fead 100644 (file)
@@ -108,5 +108,8 @@ void dcn35_update_cursor_offload_pipe(struct dc *dc, const struct pipe_ctx *pipe
 void dcn35_notify_cursor_offload_drr_update(struct dc *dc, struct dc_state *context,
                                            const struct dc_stream_state *stream);
 void dcn35_program_cursor_offload_now(struct dc *dc, const struct pipe_ctx *pipe);
+void dcn35_disable_link_output(struct dc_link *link,
+               const struct link_resource *link_res,
+               enum signal_type signal);
 
 #endif /* __DC_HWSS_DCN35_H__ */
index 5a66c9db267094a540188ec6a6d4496971b428dd..81bd36f3381dbd91bd3729ff601f31c3bd261aa8 100644 (file)
@@ -113,7 +113,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
        .enable_lvds_link_output = dce110_enable_lvds_link_output,
        .enable_tmds_link_output = dce110_enable_tmds_link_output,
        .enable_dp_link_output = dce110_enable_dp_link_output,
-       .disable_link_output = dcn32_disable_link_output,
+       .disable_link_output = dcn35_disable_link_output,
        .z10_restore = dcn35_z10_restore,
        .z10_save_init = dcn31_z10_save_init,
        .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,