From: Ashley Thomas <ashley.thom...@amd.com>

[why]
When link training failures occur for eDP, dp_disable_link_phy
is called which powers OFF eDP panel. After link training retry
delay, the next retry begins by calling dp_enable_link_phy
which does not issue a correspnding eDP panel power ON, leaving
panel powered OFF which leads to display OFF/dark.

[how]
Power ON eDP before next link training retry.

Signed-off-by: Ashley Thomas <ashley.thom...@amd.com>
Acked-by: Aurabindo Pillai <aurabindo.pil...@amd.com>
---
 .../gpu/drm/amd/display/dc/core/dc_link_dp.c  |  6 ++
 .../drm/amd/display/dc/core/dc_link_hwss.c    |  6 ++
 .../display/dc/dce110/dce110_hw_sequencer.c   | 84 ++++++++++++++-----
 3 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index e4b3b71dad03..47fb09f41bfb 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -1619,6 +1619,9 @@ bool perform_link_training_with_retries(
 
        for (j = 0; j < attempts; ++j) {
 
+               DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u 
of %d\n",
+                       __func__, (unsigned int)j + 1, attempts);
+
                dp_enable_link_phy(
                        link,
                        signal,
@@ -1647,6 +1650,9 @@ bool perform_link_training_with_retries(
                if (j == (attempts - 1))
                        break;
 
+               DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n",
+                       __func__, (unsigned int)j + 1, attempts);
+
                dp_disable_link_phy(link, signal);
 
                msleep(delay_between_attempts);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index dd88eb348dfa..81c026319ccd 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -104,6 +104,12 @@ void dp_enable_link_phy(
        struct clock_source *dp_cs =
                        link->dc->res_pool->dp_clock_source;
        unsigned int i;
+
+       if (link->connector_signal == SIGNAL_TYPE_EDP) {
+               link->dc->hwss.edp_power_control(link, true);
+               link->dc->hwss.edp_wait_for_hpd_ready(link, true);
+       }
+
        /* If the current pixel clock source is not DTO(happens after
         * switching from HDMI passive dongle to DP on the same connector),
         * switch the pixel clock source to DTO.
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 0603ddca7bd0..1002ce9979dc 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -810,37 +810,66 @@ void dce110_edp_power_control(
 
        if (power_up !=
                link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl)) 
{
+
+               unsigned long long current_ts = dm_get_timestamp(ctx);
+               unsigned long long time_since_edp_poweroff_ms =
+                               div64_u64(dm_get_elapse_time_in_ns(
+                                               ctx,
+                                               current_ts,
+                                               
link->link_trace.time_stamp.edp_poweroff), 1000000);
+               unsigned long long time_since_edp_poweron_ms =
+                               div64_u64(dm_get_elapse_time_in_ns(
+                                               ctx,
+                                               current_ts,
+                                               
link->link_trace.time_stamp.edp_poweron), 1000000);
+               DC_LOG_HW_RESUME_S3(
+                               "%s: transition: power_up=%d current_ts=%llu 
edp_poweroff=%llu edp_poweron=%llu time_since_edp_poweroff_ms=%llu 
time_since_edp_poweron_ms=%llu",
+                               __func__,
+                               power_up,
+                               current_ts,
+                               link->link_trace.time_stamp.edp_poweroff,
+                               link->link_trace.time_stamp.edp_poweron,
+                               time_since_edp_poweroff_ms,
+                               time_since_edp_poweron_ms);
+
                /* Send VBIOS command to prompt eDP panel power */
                if (power_up) {
-                       unsigned long long current_ts = dm_get_timestamp(ctx);
-                       unsigned long long duration_in_ms =
-                                       div64_u64(dm_get_elapse_time_in_ns(
-                                                       ctx,
-                                                       current_ts,
-                                                       
link->link_trace.time_stamp.edp_poweroff), 1000000);
-                       unsigned long long wait_time_ms = 0;
-
-                       /* max 500ms from LCDVDD off to on */
-                       unsigned long long edp_poweroff_time_ms = 500;
+                       /* edp requires a min of 500ms from LCDVDD off to on */
+                       unsigned long long remaining_min_edp_poweroff_time_ms = 
500;
 
+                       /* add time defined by a patch, if any (usually patch 
extra_t12_ms is 0) */
                        if (link->local_sink != NULL)
-                               edp_poweroff_time_ms =
-                                               500 + 
link->local_sink->edid_caps.panel_patch.extra_t12_ms;
-                       if (link->link_trace.time_stamp.edp_poweroff == 0)
-                               wait_time_ms = edp_poweroff_time_ms;
-                       else if (duration_in_ms < edp_poweroff_time_ms)
-                               wait_time_ms = edp_poweroff_time_ms - 
duration_in_ms;
-
-                       if (wait_time_ms) {
-                               msleep(wait_time_ms);
-                               dm_output_to_console("%s: wait %lld ms to power 
on eDP.\n",
-                                               __func__, wait_time_ms);
+                               remaining_min_edp_poweroff_time_ms +=
+                                       
link->local_sink->edid_caps.panel_patch.extra_t12_ms;
+
+                       /* Adjust remaining_min_edp_poweroff_time_ms if this is 
not the first time. */
+                       if (link->link_trace.time_stamp.edp_poweroff != 0) {
+                               if (time_since_edp_poweroff_ms < 
remaining_min_edp_poweroff_time_ms)
+                                       remaining_min_edp_poweroff_time_ms =
+                                               
remaining_min_edp_poweroff_time_ms - time_since_edp_poweroff_ms;
+                               else
+                                       remaining_min_edp_poweroff_time_ms = 0;
                        }
 
+                       if (remaining_min_edp_poweroff_time_ms) {
+                               DC_LOG_HW_RESUME_S3(
+                                               "%s: 
remaining_min_edp_poweroff_time_ms=%llu: begin wait.\n",
+                                               __func__, 
remaining_min_edp_poweroff_time_ms);
+                               msleep(remaining_min_edp_poweroff_time_ms);
+                               DC_LOG_HW_RESUME_S3(
+                                               "%s: 
remaining_min_edp_poweroff_time_ms=%llu: end wait.\n",
+                                               __func__, 
remaining_min_edp_poweroff_time_ms);
+                               dm_output_to_console("%s: wait %lld ms to power 
on eDP.\n",
+                                               __func__, 
remaining_min_edp_poweroff_time_ms);
+                       } else {
+                               DC_LOG_HW_RESUME_S3(
+                                               "%s: 
remaining_min_edp_poweroff_time_ms=%llu: no wait required.\n",
+                                               __func__, 
remaining_min_edp_poweroff_time_ms);
+                       }
                }
 
                DC_LOG_HW_RESUME_S3(
-                               "%s: Panel Power action: %s\n",
+                               "%s: BEGIN: Panel Power action: %s\n",
                                __func__, (power_up ? "On":"Off"));
 
                cntl.action = power_up ?
@@ -864,12 +893,23 @@ void dce110_edp_power_control(
 
                bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
 
+               DC_LOG_HW_RESUME_S3(
+                               "%s: END: Panel Power action: %s 
bp_result=%u\n",
+                               __func__, (power_up ? "On":"Off"),
+                               bp_result);
+
                if (!power_up)
                        /*save driver power off time stamp*/
                        link->link_trace.time_stamp.edp_poweroff = 
dm_get_timestamp(ctx);
                else
                        link->link_trace.time_stamp.edp_poweron = 
dm_get_timestamp(ctx);
 
+               DC_LOG_HW_RESUME_S3(
+                               "%s: updated values: edp_poweroff=%llu 
edp_poweron=%llu\n",
+                               __func__,
+                               link->link_trace.time_stamp.edp_poweroff,
+                               link->link_trace.time_stamp.edp_poweron);
+
                if (bp_result != BP_RESULT_OK)
                        DC_LOG_ERROR(
                                        "%s: Panel Power bp_result: %d\n",
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to