drm/amd/display: Power down hardware if set mode is not called before timeout
authorSung Lee <sung.lee@amd.com>
Thu, 25 Jun 2020 17:49:31 +0000 (13:49 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 14 Jul 2020 18:34:02 +0000 (14:34 -0400)
[WHY]
In headless systems, if set mode is not called, hardware will not be
powered down on boot, causing HW/SW discrepancies.  Powering down
hardware on boot will ensure SW state is accurate.

[HOW]
Set a timer callback on boot for 10 seconds. If set mode is not called
within that time, power down hardware. Otherwise, do not power down.

Signed-off-by: Sung Lee <sung.lee@amd.com>
Reviewed-by: Anthony Koo <Anthony.Koo@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/core/dc.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

index 4f97329d9daf2c3bf25fd694e4bbdc02c7e57991..a9a5ef250a9e3f150df42fdde56974f45f7e248e 100644 (file)
@@ -2683,6 +2683,13 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
        dal_irq_service_ack(dc->res_pool->irqs, src);
 }
 
+void dc_power_down_on_boot(struct dc *dc)
+{
+       if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW &&
+                       dc->hwss.power_down_on_boot)
+               dc->hwss.power_down_on_boot(dc);
+}
+
 void dc_set_power_state(
        struct dc *dc,
        enum dc_acpi_cm_power_state power_state)
index 389edcf3f6ce850ec0306c42563e854a3bd9abc5..c2336ca3a9e03ee8df7102f743a1548f1d95304d 100644 (file)
@@ -1029,6 +1029,7 @@ bool dc_resource_is_dsc_encoding_supported(const struct dc *dc);
  */
 bool dc_commit_state(struct dc *dc, struct dc_state *context);
 
+void dc_power_down_on_boot(struct dc *dc);
 
 struct dc_state *dc_create_state(struct dc *dc);
 struct dc_state *dc_copy_state(struct dc_state *src_ctx);
@@ -1229,6 +1230,8 @@ void dc_set_power_state(
                enum dc_acpi_cm_power_state power_state);
 void dc_resume(struct dc *dc);
 
+void dc_power_down_on_boot(struct dc *dc);
+
 #if defined(CONFIG_DRM_AMD_DC_HDCP)
 /*
  * HDCP Interfaces
index 4a70e286b4fa1c8f4f039e304552121e8b3439ae..9cdc3d2919f4b5ba893ef46d6ba36933bcfb6c90 100644 (file)
@@ -1390,38 +1390,6 @@ void dcn10_init_hw(struct dc *dc)
                }
        }
 
-       /* 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->hwseq->funcs.edp_backlight_control &&
-                               dc->hwss.power_down &&
-                               dc->hwss.edp_power_control) {
-                       dc->hwseq->funcs.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;
-                               }
-
-                       }
-               }
-       }
-
        if (!is_optimized_init_done) {
 
                for (i = 0; i < res_pool->audio_count; i++) {
@@ -1472,6 +1440,43 @@ void dcn10_init_hw(struct dc *dc)
 
 }
 
+/* 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
+ */
+void dcn10_power_down_on_boot(struct dc *dc)
+{
+       int i = 0;
+
+       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->hwseq->funcs.edp_backlight_control &&
+                               dc->hwss.power_down &&
+                               dc->hwss.edp_power_control) {
+                       dc->hwseq->funcs.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;
+                               }
+
+                       }
+               }
+       }
+}
+
 void dcn10_reset_hw_ctx_wrap(
                struct dc *dc,
                struct dc_state *context)
index 42b6e016d71e8d0582acf3a8c8191bf7b9a0077a..6d891166da8a4839e651e015dd422665fc562502 100644 (file)
@@ -109,6 +109,7 @@ void dcn10_program_pipe(
 void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx);
 void dcn10_init_hw(struct dc *dc);
 void dcn10_init_pipes(struct dc *dc, struct dc_state *context);
+void dcn10_power_down_on_boot(struct dc *dc);
 enum dc_status dce110_apply_ctx_to_hw(
                struct dc *dc,
                struct dc_state *context);
index f6a790c493219c6eb6ae615b7cfaa781cb6feb18..5c98b71c1d47ab3715301b00e2c5e3293cd12fe4 100644 (file)
@@ -30,6 +30,7 @@
 static const struct hw_sequencer_funcs dcn10_funcs = {
        .program_gamut_remap = dcn10_program_gamut_remap,
        .init_hw = dcn10_init_hw,
+       .power_down_on_boot = dcn10_power_down_on_boot,
        .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
        .apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
        .post_unlock_program_front_end = dcn10_post_unlock_program_front_end,
index bb9e9bec2f28c2cb8a6759cb5892fe47e287c5b8..2380392b916ed3a4a50fcf490fb07a43367b56dd 100644 (file)
@@ -30,6 +30,7 @@
 static const struct hw_sequencer_funcs dcn20_funcs = {
        .program_gamut_remap = dcn10_program_gamut_remap,
        .init_hw = dcn10_init_hw,
+       .power_down_on_boot =  dcn10_power_down_on_boot,
        .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
        .apply_ctx_for_surface = NULL,
        .program_front_end_for_ctx = dcn20_program_front_end_for_ctx,
index 8575de1a8ad2f617028b1d989ec4d567d07d4725..177d0dc8927a6936786344a351d90d68b742ebfb 100644 (file)
@@ -31,6 +31,7 @@
 static const struct hw_sequencer_funcs dcn21_funcs = {
        .program_gamut_remap = dcn10_program_gamut_remap,
        .init_hw = dcn10_init_hw,
+       .power_down_on_boot = dcn10_power_down_on_boot,
        .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
        .apply_ctx_for_surface = NULL,
        .program_front_end_for_ctx = dcn20_program_front_end_for_ctx,
index 066a2a723c129010e70a97bd715ae1657ffbcebd..720ce5e458d80ad65b83844d57089fc606995ea3 100644 (file)
@@ -56,6 +56,7 @@ struct hw_sequencer_funcs {
 
        /* Pipe Programming Related */
        void (*init_hw)(struct dc *dc);
+       void (*power_down_on_boot)(struct dc *dc);
        void (*enable_accelerated_mode)(struct dc *dc,
                        struct dc_state *context);
        enum dc_status (*apply_ctx_to_hw)(struct dc *dc,