drm/amd/display: Add interface to track PHY state
authorAlvin Lee <alvin.lee2@amd.com>
Wed, 10 Aug 2022 23:39:24 +0000 (19:39 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 25 Aug 2022 17:34:41 +0000 (13:34 -0400)
[Why]
Sometimes pixel clock needs to remain active after transmitter disable.

[How]
Use update_phy_state to track PHY state after stream
enable/disable and program pixel clock as needed.

Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Acked-by: Brian Chang <Brian.Chang@amd.com>
Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com>
Signed-off-by: Alvin Lee <alvin.lee2@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

index 5006263f8d56b26854564ecf9fe294f6141a8768..ced09f875e5899adb9f9a94d1af571df8657ba30 100644 (file)
@@ -1180,7 +1180,11 @@ static void disable_vbios_mode_if_required(
                                                pipe->stream_res.pix_clk_params.requested_pix_clk_100hz;
 
                                        if (pix_clk_100hz != requested_pix_clk_100hz) {
-                                               core_link_disable_stream(pipe);
+                                               if (dc->hwss.update_phy_state)
+                                                       dc->hwss.update_phy_state(dc->current_state,
+                                                                       pipe, TX_OFF_SYMCLK_OFF);
+                                               else
+                                                       core_link_disable_stream(pipe);
                                                pipe->stream->dpms_off = false;
                                        }
                                }
@@ -3063,7 +3067,11 @@ static void commit_planes_do_stream_update(struct dc *dc,
 
                        if (stream_update->dpms_off) {
                                if (*stream_update->dpms_off) {
-                                       core_link_disable_stream(pipe_ctx);
+                                       if (dc->hwss.update_phy_state)
+                                               dc->hwss.update_phy_state(dc->current_state,
+                                                               pipe_ctx, TX_OFF_SYMCLK_ON);
+                                       else
+                                               core_link_disable_stream(pipe_ctx);
                                        /* for dpms, keep acquired resources*/
                                        if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
                                                pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
@@ -3074,7 +3082,11 @@ static void commit_planes_do_stream_update(struct dc *dc,
                                        if (get_seamless_boot_stream_count(context) == 0)
                                                dc->hwss.prepare_bandwidth(dc, dc->current_state);
 
-                                       core_link_enable_stream(dc->current_state, pipe_ctx);
+                                       if (dc->hwss.update_phy_state)
+                                               dc->hwss.update_phy_state(dc->current_state,
+                                                               pipe_ctx, TX_ON_SYMCLK_ON);
+                                       else
+                                               core_link_enable_stream(dc->current_state, pipe_ctx);
                                }
                        }
 
index 48dad093ae8ba845a7dbdaecdf1b1b308bd6b0a7..f92bbc86772e1b238bbe535551200bb9669d5e11 100644 (file)
@@ -4519,7 +4519,11 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
                pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
                                pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
-                       core_link_disable_stream(pipe_ctx);
+                       if (link->dc->hwss.update_phy_state)
+                               link->dc->hwss.update_phy_state(link->dc->current_state,
+                                               pipe_ctx, TX_OFF_SYMCLK_OFF);
+                       else
+                               core_link_disable_stream(pipe_ctx);
                }
        }
 
@@ -4527,7 +4531,11 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
                pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
                                pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
-                       core_link_enable_stream(link->dc->current_state, pipe_ctx);
+                       if (link->dc->hwss.update_phy_state)
+                               link->dc->hwss.update_phy_state(link->dc->current_state,
+                                               pipe_ctx, TX_ON_SYMCLK_ON);
+                       else
+                               core_link_enable_stream(link->dc->current_state, pipe_ctx);
                }
        }
 }
index 9544abf75e846eab97013154b00e8437be8a399f..b18efe988830a7e15cb61fc94e07677676652987 100644 (file)
@@ -232,6 +232,7 @@ struct dc_link {
 
        struct gpio *hpd_gpio;
        enum dc_link_fec_state fec_state;
+       enum phy_state phy_state;
 };
 
 const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
index 38a67051d470f24cd1407a0a828b035760b7d36c..801206aed63a145dcb89bc52a6bcfddb96b63b0e 100644 (file)
@@ -1577,8 +1577,12 @@ static enum dc_status apply_single_controller_ctx_to_hw(
        if (dc_is_dp_signal(pipe_ctx->stream->signal))
                dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG);
 
-       if (!stream->dpms_off)
-               core_link_enable_stream(context, pipe_ctx);
+       if (!stream->dpms_off) {
+               if (dc->hwss.update_phy_state)
+                       dc->hwss.update_phy_state(context, pipe_ctx, TX_ON_SYMCLK_ON);
+               else
+                       core_link_enable_stream(context, pipe_ctx);
+       }
 
        /* DCN3.1 FPGA Workaround
         * Need to enable HPO DP Stream Encoder before setting OTG master enable.
index 884fa060f37514970c87370a3acda731c0f04f39..cf439ed270de119f74556236b1f6fa2a1416668b 100644 (file)
@@ -2361,9 +2361,12 @@ static void dcn20_reset_back_end_for_pipe(
                 * screen only, the dpms_off would be true but
                 * VBIOS lit up eDP, so check link status too.
                 */
-               if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
-                       core_link_disable_stream(pipe_ctx);
-               else if (pipe_ctx->stream_res.audio)
+               if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) {
+                       if (dc->hwss.update_phy_state)
+                               dc->hwss.update_phy_state(dc->current_state, pipe_ctx, TX_OFF_SYMCLK_OFF);
+                       else
+                               core_link_disable_stream(pipe_ctx);
+               } else if (pipe_ctx->stream_res.audio)
                        dc->hwss.disable_audio_stream(pipe_ctx);
 
                /* free acquired resources */
index 1ed1404e969df2e82ab14fb2f56860527e6fb8a0..8d83b611507afa348d9c03a2629ea495d03c1f88 100644 (file)
@@ -553,9 +553,12 @@ static void dcn31_reset_back_end_for_pipe(
                 * screen only, the dpms_off would be true but
                 * VBIOS lit up eDP, so check link status too.
                 */
-               if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
-                       core_link_disable_stream(pipe_ctx);
-               else if (pipe_ctx->stream_res.audio)
+               if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) {
+                       if (dc->hwss.update_phy_state)
+                               dc->hwss.update_phy_state(dc->current_state, pipe_ctx, TX_OFF_SYMCLK_OFF);
+                       else
+                               core_link_disable_stream(pipe_ctx);
+               } else if (pipe_ctx->stream_res.audio)
                        dc->hwss.disable_audio_stream(pipe_ctx);
 
                /* free acquired resources */
index d1249fe1e412c88654a4a4eb36fc5e20dc4a05a4..3b1c6603ae0c616a49505404d21f847fb2da6923 100644 (file)
@@ -1218,3 +1218,35 @@ bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
                return true;
        return false;
 }
+
+void dcn32_update_phy_state(struct dc_state *state, struct pipe_ctx *pipe_ctx,
+               enum phy_state target_state)
+{
+       enum phy_state current_state = pipe_ctx->stream->link->phy_state;
+
+       if (current_state == target_state) {
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       if (target_state == TX_OFF_SYMCLK_OFF) {
+               core_link_disable_stream(pipe_ctx);
+               pipe_ctx->stream->link->phy_state = TX_OFF_SYMCLK_OFF;
+       } else if (target_state == TX_ON_SYMCLK_ON) {
+               core_link_enable_stream(state, pipe_ctx);
+               pipe_ctx->stream->link->phy_state = TX_ON_SYMCLK_ON;
+       } else if (target_state == TX_OFF_SYMCLK_ON) {
+               if (current_state == TX_ON_SYMCLK_ON) {
+                       core_link_disable_stream(pipe_ctx);
+                       pipe_ctx->stream->link->phy_state = TX_OFF_SYMCLK_OFF;
+               }
+
+               pipe_ctx->clock_source->funcs->program_pix_clk(
+                       pipe_ctx->clock_source,
+                       &pipe_ctx->stream_res.pix_clk_params,
+                       dp_get_link_encoding_format(&pipe_ctx->link_config.dp_link_settings),
+                       &pipe_ctx->pll_settings);
+               pipe_ctx->stream->link->phy_state = TX_OFF_SYMCLK_ON;
+       } else
+               BREAK_TO_DEBUGGER();
+}
index 083f3aeb54f01ff645cb10c60baf0f3fdaf51d2f..221e31144d501b0487da5f5b6f81c3f7161b09fb 100644 (file)
@@ -84,4 +84,7 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
 
 bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);
 
+void dcn32_update_phy_state(struct dc_state *state, struct pipe_ctx *pipe_ctx,
+               enum phy_state target_state);
+
 #endif /* __DC_HWSS_DCN32_H__ */
index c279a25ea2935a15d7b3ec5ed2f718f2db111b65..28d2202181332488886039574f67c4a775ed0cae 100644 (file)
@@ -104,6 +104,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
        .commit_subvp_config = dcn32_commit_subvp_config,
        .subvp_pipe_control_lock = dcn32_subvp_pipe_control_lock,
        .update_visual_confirm_color = dcn20_update_visual_confirm_color,
+       .update_phy_state = dcn32_update_phy_state,
 };
 
 static const struct hwseq_private_funcs dcn32_private_funcs = {
index d89bd55f110feadb3f3e4563e6b532c14509d157..437b64e8737732f11ec17d5dbe768d3aedc33328 100644 (file)
@@ -268,6 +268,12 @@ enum dc_lut_mode {
        LUT_RAM_B
 };
 
+enum phy_state {
+       TX_OFF_SYMCLK_OFF,
+       TX_ON_SYMCLK_ON,
+       TX_OFF_SYMCLK_ON
+};
+
 /**
  * speakersToChannels
  *
index ccb3c719fc4dee0c3720d8f09b8128c50502c39c..a4e02b0ace249fae5be5288999300767a7effb32 100644 (file)
@@ -245,6 +245,8 @@ struct hw_sequencer_funcs {
                        struct tg_color *color,
                        int mpcc_id);
 
+       void (*update_phy_state)(struct dc_state *state, struct pipe_ctx *pipe_ctx, enum phy_state target_state);
+
        void (*commit_subvp_config)(struct dc *dc, struct dc_state *context);
        void (*subvp_pipe_control_lock)(struct dc *dc,
                        struct dc_state *context,