From: Karthi Kandasamy <[email protected]>

[Why & How]
During the HDR<->SDR toggle when the eDP link is held in a forced PSR
(freeze) state,
the normal stream/link teardown re-programming the panel would blank the
frozen frame
and disrupt the freeze; to prevent this, gate the eDP teardown path,
keeping the link
and PSR/Replay state intact for the duration of the forced PSR hold.
The blank_stream and disable_link_output gates already exist.

Acked-by: Tom Chung <[email protected]>
Signed-off-by: Karthi Kandasamy <[email protected]>
Signed-off-by: James Lin <[email protected]>
---
 .../amd/display/dc/hwss/dce110/dce110_hwseq.c |  7 +++++--
 .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c   | 19 +++++++++++++------
 .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   | 17 ++++++++++++-----
 .../amd/display/dc/hwss/dcn314/dcn314_hwseq.c |  8 +++++---
 .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   |  7 +++++--
 .../amd/display/dc/hwss/dcn60/dcn60_hwseq.c   |  8 ++++++--
 6 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index 8b47cdeeb1fb..ff0c6e64c2b4 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -3605,8 +3605,11 @@ void dce110_disable_link_output(struct dc_link *link,
        else if (dmcu != NULL && dmcu->funcs->lock_phy)
                dmcu->funcs->lock_phy(dmcu);
 
-       link_hwss->disable_link_output(link, link_res, signal);
-       link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+       if (!(signal == SIGNAL_TYPE_EDP &&
+                       link->forced_psr_active)) {
+               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
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index 850639b6fd9b..2739f7acce98 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -1346,7 +1346,12 @@ static void dcn10_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)
+       if (link->connector_signal == SIGNAL_TYPE_EDP &&
+           link->forced_psr_active) {
+               /* forced psr is active for seamless switch; skip dpms-off. */
+               if (pipe_ctx->stream_res.audio)
+                       dc->hwss.disable_audio_stream(pipe_ctx);
+       } else if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
                dc->link_srv->set_dpms_off(pipe_ctx);
        else if (pipe_ctx->stream_res.audio)
                dc->hwss.disable_audio_stream(pipe_ctx);
@@ -1370,13 +1375,15 @@ static void dcn10_reset_back_end_for_pipe(
         * parent pipe.
         */
        if (pipe_ctx->top_pipe == NULL) {
+               if (!(link->connector_signal == SIGNAL_TYPE_EDP &&
+                       link->forced_psr_active)) {
+                       if (pipe_ctx->stream_res.abm)
+                               dc->hwss.set_abm_immediate_disable(pipe_ctx);
 
-               if (pipe_ctx->stream_res.abm)
-                       dc->hwss.set_abm_immediate_disable(pipe_ctx);
+                       
pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
 
-               
pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
-
-               
pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, 
false);
+                       
pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, 
false);
+               }
                set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, 
NULL);
                if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
                        pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 
0;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 16bb6f678567..66e2a6eb41c0 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -2849,7 +2849,12 @@ 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)
+       if (link->connector_signal == SIGNAL_TYPE_EDP &&
+           link->forced_psr_active) {
+               /* forced psr is active for seamless switch; skip dpms-off. */
+               if (pipe_ctx->stream_res.audio)
+                       dc->hwss.disable_audio_stream(pipe_ctx);
+       } else if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
                dc->link_srv->set_dpms_off(pipe_ctx);
        else if (pipe_ctx->stream_res.audio)
                dc->hwss.disable_audio_stream(pipe_ctx);
@@ -2874,12 +2879,14 @@ void dcn20_reset_back_end_for_pipe(
         * parent pipe.
         */
        if (pipe_ctx->top_pipe == NULL) {
+               if (!(link->connector_signal == SIGNAL_TYPE_EDP &&
+                               link->forced_psr_active)) {
+                       dc->hwss.set_abm_immediate_disable(pipe_ctx);
 
-               dc->hwss.set_abm_immediate_disable(pipe_ctx);
-
-               
pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
+                       
pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
 
-               
pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, 
false);
+                       
pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, 
false);
+               }
                if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
                        pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
                                        pipe_ctx->stream_res.tg, 
&pipe_ctx->stream->timing);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
index 6ddc678bacf9..56d41c6fa3ee 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
@@ -517,9 +517,11 @@ void dcn314_disable_link_output(struct dc_link *link,
                link->dc->hwss.edp_backlight_control(link, false);
        else if (dmcu != NULL && dmcu->funcs->lock_phy)
                dmcu->funcs->lock_phy(dmcu);
-
-       link_hwss->disable_link_output(link, link_res, signal);
-       link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+       if (!(signal == SIGNAL_TYPE_EDP &&
+               link->forced_psr_active)) {
+               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
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index 51fd2b3fe106..e188796cf272 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -1432,8 +1432,11 @@ void dcn32_disable_link_output(struct dc_link *link,
        else if (dmcu != NULL && dmcu->funcs->lock_phy)
                dmcu->funcs->lock_phy(dmcu);
 
-       link_hwss->disable_link_output(link, link_res, signal);
-       link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+       if (!(signal == SIGNAL_TYPE_EDP &&
+               link->forced_psr_active)) {
+               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
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
index b9a046584740..8ee9791b2c46 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
@@ -291,7 +291,9 @@ enum dc_status dcn60_apply_single_controller_ctx_to_hw(
                        dc_is_virtual_signal(pipe_ctx->stream->signal)))
                        dc->link_srv->set_dsc_enable(pipe_ctx, true);
        }
-       if (!stream->dpms_off)
+       if (!stream->dpms_off &&
+           !(link->connector_signal == SIGNAL_TYPE_EDP &&
+             link->forced_psr_active))
                dc->link_srv->set_dpms_on(context, pipe_ctx);
 
        /* DCN3.1 FPGA Workaround
@@ -310,7 +312,9 @@ enum dc_status dcn60_apply_single_controller_ctx_to_hw(
         * is constructed with the same sink). Make sure not to override
         * and link programming on the main.
         */
-       if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) {
+       if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM &&
+           !(link->connector_signal == SIGNAL_TYPE_EDP &&
+             link->forced_psr_active)) {
                pipe_ctx->stream->link->psr_settings.psr_feature_enabled = 
false;
                pipe_ctx->stream->link->replay_settings.replay_feature_enabled 
= false;
        }
-- 
2.43.0

Reply via email to