drm/amd/display: add delay between panel pwr off to on.
authorCharlene Liu <charlene.liu@amd.com>
Tue, 20 Mar 2018 18:53:04 +0000 (14:53 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 11 Apr 2018 18:08:06 +0000 (13:08 -0500)
As per eDP 1.4 spec, there must be at least 500ms delay
between eDP power off and on.
This change added time stamp when edp power off, which can
be used to calculate duration time when edp power on.
If duration less than 500ms, add a wait.

Signed-off-by: Charlene Liu <charlene.liu@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.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/dm_services.h

index fe29125215b5c2cf47a76e8c5be054ae7af77c69..0229c7edb8ad75242b89416e52e39373b0e105fc 100644 (file)
@@ -43,6 +43,13 @@ unsigned long long dm_get_timestamp(struct dc_context *ctx)
        return timespec64_to_ns(&time);
 }
 
+unsigned long long dm_get_elapse_time_in_ns(struct dc_context *ctx,
+               unsigned long long current_time_stamp,
+               unsigned long long last_time_stamp)
+{
+       return current_time_stamp - last_time_stamp;
+}
+
 void dm_perf_trace_timestamp(const char *func_name, unsigned int line)
 {
 }
index fb4d9eafdc6e20b96fe66c0bbde8624293b2cf12..eeff9874129330b55f8bc0225d5eaaf9497f14fe 100644 (file)
@@ -51,6 +51,14 @@ struct link_mst_stream_allocation_table {
        struct link_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM];
 };
 
+struct time_stamp {
+       uint64_t edp_poweroff;
+       uint64_t edp_poweron;
+};
+
+struct link_trace {
+       struct time_stamp time_stamp;
+};
 /*
  * A link contains one or more sinks and their connected status.
  * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported.
@@ -114,6 +122,7 @@ struct dc_link {
 
        struct dc_link_status link_status;
 
+       struct link_trace link_trace;
 };
 
 const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
index e8df50f30e5b0811c69a5ba0a5b58a58adea0ee6..db2d15dfb831beeda465cda80dd510df87f685a6 100644 (file)
@@ -849,6 +849,28 @@ void hwss_edp_power_control(
 
        if (power_up != is_panel_powered_on(hwseq)) {
                /* 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 =
+                                       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 */
+                       if (link->link_trace.time_stamp.edp_poweroff == 0)
+                               wait_time_ms = 500;
+                       else if (duration_in_ms < 500)
+                               wait_time_ms = 500 - 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);
+                       }
+
+               }
 
                DC_LOG_HW_RESUME_S3(
                                "%s: Panel Power action: %s\n",
@@ -862,9 +884,14 @@ void hwss_edp_power_control(
                cntl.coherent = false;
                cntl.lanes_number = LANE_COUNT_FOUR;
                cntl.hpd_sel = link->link_enc->hpd_source;
-
                bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
 
+               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);
+
                if (bp_result != BP_RESULT_OK)
                        DC_LOG_ERROR(
                                        "%s: Panel Power bp_result: %d\n",
index 22e7ee7dcd26d1b5cd1cb52afb8a5be55c464b6c..8eafe1af8a5ea3fb555b7fa6d3cc44836fb2fa39 100644 (file)
@@ -341,6 +341,10 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id);
 
 unsigned long long dm_get_timestamp(struct dc_context *ctx);
 
+unsigned long long dm_get_elapse_time_in_ns(struct dc_context *ctx,
+               unsigned long long current_time_stamp,
+               unsigned long long last_time_stamp);
+
 /*
  * performance tracing
  */