From: Sung Lee <[email protected]>

[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 <[email protected]>
Reviewed-by: Anthony Koo <[email protected]>
Acked-by: Rodrigo Siqueira <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  6 ++
 drivers/gpu/drm/amd/display/dc/dc.h           |  3 +
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 69 ++++++++++---------
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.h |  1 +
 .../gpu/drm/amd/display/dc/dcn10/dcn10_init.c |  1 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c |  1 +
 .../gpu/drm/amd/display/dc/dcn21/dcn21_init.c |  1 +
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |  1 +
 8 files changed, 51 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 942ceb0f6383..8d935020068f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2683,6 +2683,12 @@ 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,
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 389edcf3f6ce..c2336ca3a9e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -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
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 6711ff908bcf..20466cad6ade 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1393,38 +1393,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++) {
@@ -1475,6 +1443,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)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
index 42b6e016d71e..6d891166da8a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
index f6a790c49321..5c98b71c1d47 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
index bb9e9bec2f28..2380392b916e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c 
b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
index 8575de1a8ad2..177d0dc8927a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
index 066a2a723c12..720ce5e458d8 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -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,
-- 
2.27.0

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to