From: Nicholas Kazlauskas <nicholas.kazlaus...@amd.com>

[Why]
DPP Root clock optimization when combined with 4to1 MPC combine results
in the screen turning black.

This is because the DPPCLK is stopped during the middle of an
optimize_bandwidth sequence during commit_minimal_transition without
going through plane power down/power up.

[How]
The intent of a 0Hz DPP clock through update_clocks is to disable the
DTO. This differs from the behavior of stopping the DPPCLK entirely
(utilizing a 0Hz clock on some ASIC) so it's better to move this logic
to reside next to plane power up/power down where we gate the HUBP/DPP
DOMAIN.

The new  sequence should be:
Power down: PG enabled -> RCO on
Power up: RCO off -> PG disabled

Rename power_on_plane to power_on_plane_resources to reflect the
actual operation that's occurring.

Cc: sta...@vger.kernel.org
Cc: Mario Limonciello <mario.limoncie...@amd.com>
Reviewed-by: Jun Lei <jun....@amd.com>
Acked-by: Qingqing Zhuo <qingqing.z...@amd.com>
Signed-off-by: Nicholas Kazlauskas <nicholas.kazlaus...@amd.com>
---
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++++--
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c    |  8 ++++--
 .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c | 13 ++-------
 .../drm/amd/display/dc/dcn314/dcn314_dccg.c   | 23 +++++++++++++++
 .../drm/amd/display/dc/dcn314/dcn314_hwseq.c  | 10 +++++++
 .../drm/amd/display/dc/dcn314/dcn314_hwseq.h  |  2 ++
 .../drm/amd/display/dc/dcn314/dcn314_init.c   |  1 +
 drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h  | 28 +++++++++++--------
 .../amd/display/dc/inc/hw_sequencer_private.h |  4 +++
 9 files changed, 74 insertions(+), 27 deletions(-)

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 46ca88741cb8..1c3b6f25a782 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
@@ -726,11 +726,15 @@ void dcn10_hubp_pg_control(
        }
 }
 
-static void power_on_plane(
+static void power_on_plane_resources(
        struct dce_hwseq *hws,
        int plane_id)
 {
        DC_LOGGER_INIT(hws->ctx->logger);
+
+       if (hws->funcs.dpp_root_clock_control)
+               hws->funcs.dpp_root_clock_control(hws, plane_id, true);
+
        if (REG(DC_IP_REQUEST_CNTL)) {
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 1);
@@ -1237,11 +1241,15 @@ void dcn10_plane_atomic_power_down(struct dc *dc,
                        hws->funcs.hubp_pg_control(hws, hubp->inst, false);
 
                dpp->funcs->dpp_reset(dpp);
+
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 0);
                DC_LOG_DEBUG(
                                "Power gated front end %d\n", hubp->inst);
        }
+
+       if (hws->funcs.dpp_root_clock_control)
+               hws->funcs.dpp_root_clock_control(hws, dpp->inst, false);
 }
 
 /* disable HW used by plane.
@@ -2462,7 +2470,7 @@ static void dcn10_enable_plane(
 
        undo_DEGVIDCN10_253_wa(dc);
 
-       power_on_plane(dc->hwseq,
+       power_on_plane_resources(dc->hwseq,
                pipe_ctx->plane_res.hubp->inst);
 
        /* enable DCFCLK current DCHUB */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 69ea1f4ea749..9ca162ea0d07 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1130,11 +1130,15 @@ void dcn20_blank_pixel_data(
 }
 
 
-static void dcn20_power_on_plane(
+static void dcn20_power_on_plane_resources(
        struct dce_hwseq *hws,
        struct pipe_ctx *pipe_ctx)
 {
        DC_LOGGER_INIT(hws->ctx->logger);
+
+       if (hws->funcs.dpp_root_clock_control)
+               hws->funcs.dpp_root_clock_control(hws, 
pipe_ctx->plane_res.dpp->inst, true);
+
        if (REG(DC_IP_REQUEST_CNTL)) {
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 1);
@@ -1158,7 +1162,7 @@ static void dcn20_enable_plane(struct dc *dc, struct 
pipe_ctx *pipe_ctx,
        //if (dc->debug.sanity_checks) {
        //      dcn10_verify_allow_pstate_change_high(dc);
        //}
-       dcn20_power_on_plane(dc->hwseq, pipe_ctx);
+       dcn20_power_on_plane_resources(dc->hwseq, pipe_ctx);
 
        /* enable DCFCLK current DCHUB */
        
pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c 
b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
index 7f34418e6308..7d2b982506fd 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
@@ -66,17 +66,8 @@ void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, 
int req_dppclk)
                REG_UPDATE(DPPCLK_DTO_CTRL,
                                DPPCLK_DTO_ENABLE[dpp_inst], 1);
        } else {
-               //DTO must be enabled to generate a 0Hz clock output
-               if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
-                       REG_UPDATE(DPPCLK_DTO_CTRL,
-                                       DPPCLK_DTO_ENABLE[dpp_inst], 1);
-                       REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
-                                       DPPCLK0_DTO_PHASE, 0,
-                                       DPPCLK0_DTO_MODULO, 1);
-               } else {
-                       REG_UPDATE(DPPCLK_DTO_CTRL,
-                                       DPPCLK_DTO_ENABLE[dpp_inst], 0);
-               }
+               REG_UPDATE(DPPCLK_DTO_CTRL,
+                               DPPCLK_DTO_ENABLE[dpp_inst], 0);
        }
        dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
 }
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c 
b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
index 0b769ee71405..081ce168f621 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
@@ -289,8 +289,31 @@ static void dccg314_set_valid_pixel_rate(
        dccg314_set_dtbclk_dto(dccg, &dto_params);
 }
 
+static void dccg314_dpp_root_clock_control(
+               struct dccg *dccg,
+               unsigned int dpp_inst,
+               bool clock_on)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       if (clock_on) {
+               /* turn off the DTO and leave phase/modulo at max */
+               REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 0);
+               REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
+                         DPPCLK0_DTO_PHASE, 0xFF,
+                         DPPCLK0_DTO_MODULO, 0xFF);
+       } else {
+               /* turn on the DTO to generate a 0hz clock */
+               REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 1);
+               REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
+                         DPPCLK0_DTO_PHASE, 0,
+                         DPPCLK0_DTO_MODULO, 1);
+       }
+}
+
 static const struct dccg_funcs dccg314_funcs = {
        .update_dpp_dto = dccg31_update_dpp_dto,
+       .dpp_root_clock_control = dccg314_dpp_root_clock_control,
        .get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
        .dccg_init = dccg31_init,
        .set_dpstreamclk = dccg314_set_dpstreamclk,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
index bcc03426fc3e..40c488b26901 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
@@ -390,6 +390,16 @@ void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
                                pix_per_cycle);
 }
 
+void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int 
dpp_inst, bool clock_on)
+{
+       if (!hws->ctx->dc->debug.root_clock_optimization.bits.dpp)
+               return;
+
+       if (hws->ctx->dc->res_pool->dccg->funcs->dpp_root_clock_control)
+               hws->ctx->dc->res_pool->dccg->funcs->dpp_root_clock_control(
+                       hws->ctx->dc->res_pool->dccg, dpp_inst, clock_on);
+}
+
 void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, 
bool power_on)
 {
        struct dc_context *ctx = hws->ctx;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h 
b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
index c419d3dbdfee..c786d5e6a428 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
@@ -43,4 +43,6 @@ void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx);
 
 void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, 
bool power_on);
 
+void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int 
dpp_inst, bool clock_on);
+
 #endif /* __DC_HWSS_DCN314_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c 
b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
index 343f4d9dd5e3..5267e901a35c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
@@ -137,6 +137,7 @@ static const struct hwseq_private_funcs 
dcn314_private_funcs = {
        .plane_atomic_disable = dcn20_plane_atomic_disable,
        .plane_atomic_power_down = dcn10_plane_atomic_power_down,
        .enable_power_gating_plane = dcn314_enable_power_gating_plane,
+       .dpp_root_clock_control = dcn314_dpp_root_clock_control,
        .hubp_pg_control = dcn314_hubp_pg_control,
        .program_all_writeback_pipes_in_tree = 
dcn30_program_all_writeback_pipes_in_tree,
        .update_odm = dcn314_update_odm,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
index ce006762f257..09de03699cc2 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
@@ -148,18 +148,22 @@ struct dccg_funcs {
                struct dccg *dccg,
                int inst);
 
-void (*set_pixel_rate_div)(
-        struct dccg *dccg,
-        uint32_t otg_inst,
-        enum pixel_rate_div k1,
-        enum pixel_rate_div k2);
-
-void (*set_valid_pixel_rate)(
-        struct dccg *dccg,
-       int ref_dtbclk_khz,
-        int otg_inst,
-        int pixclk_khz);
-
+       void (*set_pixel_rate_div)(
+               struct dccg *dccg,
+               uint32_t otg_inst,
+               enum pixel_rate_div k1,
+               enum pixel_rate_div k2);
+
+       void (*set_valid_pixel_rate)(
+               struct dccg *dccg,
+               int ref_dtbclk_khz,
+               int otg_inst,
+               int pixclk_khz);
+
+       void (*dpp_root_clock_control)(
+                       struct dccg *dccg,
+                       unsigned int dpp_inst,
+                       bool clock_on);
 };
 
 #endif //__DAL_DCCG_H__
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
index 45d37c584551..5f63b67975cf 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
@@ -115,6 +115,10 @@ struct hwseq_private_funcs {
        void (*plane_atomic_disable)(struct dc *dc, struct pipe_ctx *pipe_ctx);
        void (*enable_power_gating_plane)(struct dce_hwseq *hws,
                bool enable);
+       void (*dpp_root_clock_control)(
+                       struct dce_hwseq *hws,
+                       unsigned int dpp_inst,
+                       bool clock_on);
        void (*dpp_pg_control)(struct dce_hwseq *hws,
                        unsigned int dpp_inst,
                        bool power_on);
-- 
2.34.1

Reply via email to