drm/amd/display: Keep clocks high before seamless boot done
authorAnthony Koo <Anthony.Koo@amd.com>
Sat, 9 Feb 2019 01:50:51 +0000 (20:50 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 19 Mar 2019 20:04:03 +0000 (15:04 -0500)
[Why]
UEFI boot usually uses a boot profile that uses higher clocks
and watermark settings.
UEFI boot surface is less optimal, for example it uses linear surface

[How]
Before we finish our seamless boot sequence, keep the clock and
watermark settings from boot.
Update to optimal settings only after first flip away from UEFI
frame buffer.

Signed-off-by: Anthony Koo <Anthony.Koo@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@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_resource.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/inc/clock_source.h

index 679f1441f3b7b0cb387f15472965f9b5220d7e0d..96090d6ce7a92e49d3ec5879c6ee2c7c556c44e9 100644 (file)
@@ -971,7 +971,7 @@ static bool context_changed(
        return false;
 }
 
-bool dc_validate_seamless_boot_timing(struct dc *dc,
+bool dc_validate_seamless_boot_timing(const struct dc *dc,
                                const struct dc_sink *sink,
                                struct dc_crtc_timing *crtc_timing)
 {
@@ -1062,7 +1062,13 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
        if (!dcb->funcs->is_accelerated_mode(dcb))
                dc->hwss.enable_accelerated_mode(dc, context);
 
-       dc->hwss.prepare_bandwidth(dc, context);
+       for (i = 0; i < context->stream_count; i++) {
+               if (context->streams[i]->apply_seamless_boot_optimization)
+                       dc->optimize_seamless_boot = true;
+       }
+
+       if (!dc->optimize_seamless_boot)
+               dc->hwss.prepare_bandwidth(dc, context);
 
        /* re-program planes for existing stream, in case we need to
         * free up plane resource for later use
@@ -1137,8 +1143,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
 
        dc_enable_stereo(dc, context, dc_streams, context->stream_count);
 
-       /* pplib is notified if disp_num changed */
-       dc->hwss.optimize_bandwidth(dc, context);
+       if (!dc->optimize_seamless_boot)
+               /* pplib is notified if disp_num changed */
+               dc->hwss.optimize_bandwidth(dc, context);
 
        for (i = 0; i < context->stream_count; i++)
                context->streams[i]->mode_changed = false;
@@ -1181,7 +1188,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
        int i;
        struct dc_state *context = dc->current_state;
 
-       if (dc->optimized_required == false)
+       if (!dc->optimized_required || dc->optimize_seamless_boot)
                return true;
 
        post_surface_trace(dc);
@@ -1699,7 +1706,16 @@ static void commit_planes_for_stream(struct dc *dc,
        int i, j;
        struct pipe_ctx *top_pipe_to_program = NULL;
 
-       if (update_type == UPDATE_TYPE_FULL) {
+       if (dc->optimize_seamless_boot && surface_count > 0) {
+               /* Optimize seamless boot flag keeps clocks and watermarks high until
+                * first flip. After first flip, optimization is required to lower
+                * bandwidth.
+                */
+               dc->optimize_seamless_boot = false;
+               dc->optimized_required = true;
+       }
+
+       if (update_type == UPDATE_TYPE_FULL && !dc->optimize_seamless_boot) {
                dc->hwss.prepare_bandwidth(dc, context);
                context_clock_trace(dc, context);
        }
index 0c3e8663d7b47e6fecf0b5fc7dc0055a328b65ed..7f3c7defb5401cc564eb616f952f13519e7a6f3e 100644 (file)
@@ -1858,6 +1858,7 @@ enum dc_status resource_map_pool_resources(
        struct dc_context *dc_ctx = dc->ctx;
        struct pipe_ctx *pipe_ctx = NULL;
        int pipe_idx = -1;
+       struct dc_bios *dcb = dc->ctx->dc_bios;
 
        /* TODO Check if this is needed */
        /*if (!resource_is_stream_unchanged(old_context, stream)) {
@@ -1872,6 +1873,13 @@ enum dc_status resource_map_pool_resources(
 
        calculate_phy_pix_clks(stream);
 
+       /* TODO: Check Linux */
+       if (dc->config.allow_seamless_boot_optimization &&
+                       !dcb->funcs->is_accelerated_mode(dcb)) {
+               if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing))
+                       stream->apply_seamless_boot_optimization = true;
+       }
+
        if (stream->apply_seamless_boot_optimization)
                pipe_idx = acquire_resource_from_hw_enabled_state(
                                &context->res_ctx,
index ae60c62a2e2dfdf42caa3777263f1766019cca9e..1916dae5a830e2c1115cbcc4fc1a3bbdf4a2f49a 100644 (file)
@@ -183,6 +183,7 @@ struct dc_config {
        bool disable_disp_pll_sharing;
        bool fbc_support;
        bool optimize_edp_link_rate;
+       bool allow_seamless_boot_optimization;
 };
 
 enum visual_confirm {
@@ -328,8 +329,12 @@ struct dc {
        struct hw_sequencer_funcs hwss;
        struct dce_hwseq *hwseq;
 
+       /* Require to optimize clocks and bandwidth for added/removed planes */
        bool optimized_required;
 
+       /* Require to maintain clocks and bandwidth for UEFI enabled HW */
+       bool optimize_seamless_boot;
+
        /* FBC compressor */
        struct compressor *fbc_compressor;
 
@@ -625,7 +630,7 @@ struct dc_validation_set {
        uint8_t plane_count;
 };
 
-bool dc_validate_seamless_boot_timing(struct dc *dc,
+bool dc_validate_seamless_boot_timing(const struct dc *dc,
                                const struct dc_sink *sink,
                                struct dc_crtc_timing *crtc_timing);
 
index 71d5777de96197104c649779693c1dc6f850a569..f70437aae8e08538492bd2a2b430c2375a96d279 100644 (file)
@@ -978,7 +978,7 @@ static bool dce110_clock_source_power_down(
 }
 
 static bool get_pixel_clk_frequency_100hz(
-               struct clock_source *clock_source,
+               const struct clock_source *clock_source,
                unsigned int inst,
                unsigned int *pixel_clk_khz)
 {
index 18cc5d90b4d4fb6fce9cf2d5f0e0d966faa9d870..db67122d1384215cf9fe2eae3276143955e52c19 100644 (file)
@@ -1026,9 +1026,10 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
                 * to non-preferred front end. If pipe_ctx->stream is not NULL,
                 * we will use the pipe, so don't disable
                 */
-               if (pipe_ctx->stream != NULL &&
-                   pipe_ctx->stream_res.tg->funcs->is_tg_enabled(
-                           pipe_ctx->stream_res.tg))
+               if (can_apply_seamless_boot &&
+                       pipe_ctx->stream != NULL &&
+                       pipe_ctx->stream_res.tg->funcs->is_tg_enabled(
+                               pipe_ctx->stream_res.tg))
                        continue;
 
                /* Disable on the current state so the new one isn't cleared. */
index fe6301cb8681f43e3305ff29bc77ae4701e9d5c4..1b01a9a58d14427d0625e4c31ecf7c56326d915e 100644 (file)
@@ -167,7 +167,7 @@ struct clock_source_funcs {
                        struct pixel_clk_params *,
                        struct pll_settings *);
        bool (*get_pixel_clk_frequency_100hz)(
-                       struct clock_source *clock_source,
+                       const struct clock_source *clock_source,
                        unsigned int inst,
                        unsigned int *pixel_clk_khz);
 };