drm/amd/display: enable single dp seamless boot
authorMartin Leung <martin.leung@amd.com>
Fri, 16 Aug 2019 21:26:23 +0000 (17:26 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 3 Oct 2019 14:10:57 +0000 (09:10 -0500)
[why]
seamless boot didn't work for non edp's before

[how]
removed edp-specific code, made dp read uefi-set link settings. Also fixed
a hubbub code line to be consistent with usage of function.

Signed-off-by: Martin Leung <martin.leung@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Anthony Koo <Anthony.Koo@amd.com>
Acked-by: Leo Li <sunpeng.li@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.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c

index a31c514..d524981 100644 (file)
@@ -974,29 +974,33 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
 {
        struct timing_generator *tg;
        struct dc_link *link = sink->link;
-       unsigned int enc_inst, tg_inst;
+       unsigned int enc_inst, tg_inst, i;
+
+       // Seamless port only support single DP and EDP so far
+       if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
+               sink->sink_signal != SIGNAL_TYPE_EDP)
+               return false;
 
        /* Check for enabled DIG to identify enabled display */
        if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
                return false;
 
-       /* Check for which front end is used by this encoder.
-        * Note the inst is 1 indexed, where 0 is undefined.
-        * Note that DIG_FE can source from different OTG but our
-        * current implementation always map 1-to-1, so this code makes
-        * the same assumption and doesn't check OTG source.
-        */
        enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
 
-       /* Instance should be within the range of the pool */
-       if (enc_inst >= dc->res_pool->pipe_count)
+       if (enc_inst == ENGINE_ID_UNKNOWN)
                return false;
 
-       if (enc_inst >= dc->res_pool->stream_enc_count)
-               return false;
+       for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
+               if (dc->res_pool->stream_enc[i]->id == enc_inst) {
+                       tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
+                               dc->res_pool->stream_enc[i]);
+                       break;
+               }
+       }
 
-       tg_inst = dc->res_pool->stream_enc[enc_inst]->funcs->dig_source_otg(
-               dc->res_pool->stream_enc[enc_inst]);
+       // tg_inst not found
+       if (i == dc->res_pool->stream_enc_count)
+               return false;
 
        if (tg_inst >= dc->res_pool->timing_generator_count)
                return false;
index 15b1498..263c1c9 100644 (file)
@@ -519,7 +519,7 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin
 }
 
 
-static void read_edp_current_link_settings_on_detect(struct dc_link *link)
+static void read_current_link_settings_on_detect(struct dc_link *link)
 {
        union lane_count_set lane_count_set = { {0} };
        uint8_t link_bw_set;
@@ -554,17 +554,23 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
                        &link_bw_set, sizeof(link_bw_set));
 
        if (link_bw_set == 0) {
-               /* If standard link rates are not being used,
-                * Read DPCD 00115h to find the link rate set used
-                */
-               core_link_read_dpcd(link, DP_LINK_RATE_SET,
-                               &link_rate_set, sizeof(link_rate_set));
-
-               if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
-                       link->cur_link_settings.link_rate =
-                               link->dpcd_caps.edp_supported_link_rates[link_rate_set];
-                       link->cur_link_settings.link_rate_set = link_rate_set;
-                       link->cur_link_settings.use_link_rate_set = true;
+               if (link->connector_signal == SIGNAL_TYPE_EDP) {
+                       /* If standard link rates are not being used,
+                        * Read DPCD 00115h to find the edp link rate set used
+                        */
+                       core_link_read_dpcd(link, DP_LINK_RATE_SET,
+                                       &link_rate_set, sizeof(link_rate_set));
+
+                       // edp_supported_link_rates_count = 0 for DP
+                       if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
+                               link->cur_link_settings.link_rate =
+                                               link->dpcd_caps.edp_supported_link_rates[link_rate_set];
+                               link->cur_link_settings.link_rate_set = link_rate_set;
+                               link->cur_link_settings.use_link_rate_set = true;
+                       }
+               } else {
+                       // Link Rate not found. Seamless boot may not work.
+                       ASSERT(false);
                }
        } else {
                link->cur_link_settings.link_rate = link_bw_set;
@@ -752,6 +758,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
        struct dpcd_caps prev_dpcd_caps;
        bool same_dpcd = true;
        enum dc_connection_type new_connection_type = dc_connection_none;
+       bool perform_dp_seamless_boot = false;
        DC_LOGGER_INIT(link->ctx->logger);
 
        if (dc_is_virtual_signal(link->connector_signal))
@@ -808,15 +815,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                }
 
                case SIGNAL_TYPE_EDP: {
-                       read_edp_current_link_settings_on_detect(link);
+                       read_current_link_settings_on_detect(link);
                        detect_edp_sink_caps(link);
-                       sink_caps.transaction_type =
-                               DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+                       sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
                        sink_caps.signal = SIGNAL_TYPE_EDP;
                        break;
                }
 
                case SIGNAL_TYPE_DISPLAY_PORT: {
+
                        /* wa HPD high coming too early*/
                        if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
 
@@ -870,6 +877,17 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                                return false;
                        }
 
+                       // For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified.
+                       if (reason == DETECT_REASON_BOOT &&
+                                       dc_ctx->dc->config.power_down_display_on_boot == false &&
+                                       link->link_status.link_active == true)
+                               perform_dp_seamless_boot = true;
+
+                       if (perform_dp_seamless_boot) {
+                               read_current_link_settings_on_detect(link);
+                               link->verified_link_cap = link->reported_link_cap;
+                       }
+
                        break;
                }
 
@@ -954,10 +972,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                         *  two link trainings
                         */
 
-                       /* deal with non-mst cases */
-                       dp_verify_link_cap_with_retries(link,
-                                       &link->reported_link_cap,
-                                       LINK_TRAINING_MAX_VERIFY_RETRY);
+                       // verify link cap for SST non-seamless boot
+                       if (!perform_dp_seamless_boot)
+                               dp_verify_link_cap_with_retries(link,
+                                               &link->reported_link_cap,
+                                               LINK_TRAINING_MAX_VERIFY_RETRY);
                } else {
                        // If edid is the same, then discard new sink and revert back to original sink
                        if (same_edid) {
index 8f70295..215e93a 100644 (file)
@@ -1848,28 +1848,28 @@ static int acquire_resource_from_hw_enabled_state(
                struct dc_stream_state *stream)
 {
        struct dc_link *link = stream->link;
-       unsigned int inst, tg_inst;
+       unsigned int inst, tg_inst, i;
 
        /* Check for enabled DIG to identify enabled display */
        if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
                return -1;
 
-       /* Check for which front end is used by this encoder.
-        * Note the inst is 1 indexed, where 0 is undefined.
-        * Note that DIG_FE can source from different OTG but our
-        * current implementation always map 1-to-1, so this code makes
-        * the same assumption and doesn't check OTG source.
-        */
        inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
 
-       /* Instance should be within the range of the pool */
-       if (inst >= pool->pipe_count)
-               return -1;
+       if (inst == ENGINE_ID_UNKNOWN)
+               return false;
 
-       if (inst >= pool->stream_enc_count)
-               return -1;
+       for (i = 0; i < pool->stream_enc_count; i++) {
+               if (pool->stream_enc[i]->id == inst) {
+                       tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
+                               pool->stream_enc[i]);
+                       break;
+               }
+       }
 
-       tg_inst = pool->stream_enc[inst]->funcs->dig_source_otg(pool->stream_enc[inst]);
+       // tg_inst not found
+       if (i == pool->stream_enc_count)
+               return false;
 
        if (tg_inst >= pool->timing_generator_count)
                return false;
index b83c022..e0a6e30 100644 (file)
@@ -588,7 +588,7 @@ static void hubbub2_program_watermarks(
                        DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
        REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180);
 
-       hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
+       hubbub->funcs->allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
 }
 
 static const struct hubbub_funcs hubbub2_funcs = {
@@ -600,7 +600,8 @@ static const struct hubbub_funcs hubbub2_funcs = {
        .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
        .wm_read_state = hubbub2_wm_read_state,
        .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
-       .program_watermarks = hubbub2_program_watermarks
+       .program_watermarks = hubbub2_program_watermarks,
+       .allow_self_refresh_control = hubbub1_allow_self_refresh_control
 };
 
 void hubbub2_construct(struct dcn20_hubbub *hubbub,