drm/amd/display: Power down hw blocks on boot
authorSung Lee <sung.lee@amd.com>
Sun, 5 Apr 2020 20:40:45 +0000 (16:40 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 9 Apr 2020 14:43:16 +0000 (10:43 -0400)
[WHY]
On headless boot a DIG may be turned on by VBIOS on RN.  This leads to
display_count being non-zero in hybrid graphics cases leading to SMU
DISPLAY_OFF message not being sent.

[HOW]
Power down hardware on boot
if seamless boot is not occurring
(power_down_display_on_boot == 1)

Signed-off-by: Sung Lee <sung.lee@amd.com>
Reviewed-by: Yongqiang Sun <yongqiang.sun@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

index 0be0100..dad95f1 100644 (file)
@@ -1361,6 +1361,35 @@ void dcn10_init_hw(struct dc *dc)
                                        !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
        }
 
+       /* In headless boot cases, DIG may be turned
+        * on which causes HW/SW discrepancies.
+        * To avoid this, power down hardware on boot
+        * if DIG is turned on and seamless boot not enabled
+        */
+       if (dc->config.power_down_display_on_boot) {
+               struct dc_link *edp_link = get_edp_link(dc);
+
+               if (edp_link &&
+                       edp_link->link_enc->funcs->is_dig_enabled &&
+                       edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) {
+                       dc->hwss.edp_backlight_control(edp_link, false);
+                       dc->hwss.power_down(dc);
+                       dc->hwss.edp_power_control(edp_link, false);
+               } else {
+                       for (i = 0; i < dc->link_count; i++) {
+                               struct dc_link *link = dc->links[i];
+
+                               if (link->link_enc->funcs->is_dig_enabled &&
+                                               link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
+                                               dc->hwss.power_down) {
+                                       dc->hwss.power_down(dc);
+                                       break;
+                               }
+
+                       }
+               }
+       }
+
        for (i = 0; i < res_pool->audio_count; i++) {
                struct audio *audio = res_pool->audios[i];
 
index b9ff976..a6ed70f 100644 (file)
@@ -90,6 +90,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = {
        .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level,
        .optimize_pwr_state = dcn21_optimize_pwr_state,
        .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
+       .power_down = dce110_power_down,
 };
 
 static const struct hwseq_private_funcs dcn21_private_funcs = {
index d4c1fb2..9380721 100644 (file)
@@ -75,9 +75,13 @@ struct hw_sequencer_funcs {
        void (*wait_for_mpcc_disconnect)(struct dc *dc,
                        struct resource_pool *res_pool,
                        struct pipe_ctx *pipe_ctx);
+       void (*edp_backlight_control)(
+                       struct dc_link *link,
+                       bool enable);
        void (*program_triplebuffer)(const struct dc *dc,
                struct pipe_ctx *pipe_ctx, bool enableTripleBuffer);
        void (*update_pending_status)(struct pipe_ctx *pipe_ctx);
+       void (*power_down)(struct dc *dc);
 
        /* Pipe Lock Related */
        void (*pipe_control_lock)(struct dc *dc,