From: Leo Chen <[email protected]>

[Why & How]
There is an updated workaround for PG Repeater issue in DCN42. This PR is
addressing the dynamic power gating use cases (Driver PG) to align with
the new sequence.

Reviewed-by: Ovidiu (Ovi) Bunea <[email protected]>
Signed-off-by: Leo Chen <[email protected]>
Signed-off-by: George Zhang <[email protected]>
---
 .../amd/display/dc/dccg/dcn42/dcn42_dccg.c    | 18 +++-
 .../amd/display/dc/dccg/dcn42/dcn42_dccg.h    |  1 +
 drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h  |  1 +
 .../amd/display/dc/pg/dcn42/dcn42_pg_cntl.c   | 97 +++++++++++++------
 .../amd/display/dc/pg/dcn42/dcn42_pg_cntl.h   | 22 ++++-
 5 files changed, 99 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c 
b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
index 6cbc1f4ef411..616a896f0782 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
@@ -77,7 +77,7 @@ void dccg42_otg_drop_pixel(struct dccg *dccg,
        }
 }

-void dccg42_enable_global_fgcg(struct dccg *dccg, bool value)
+void dccg42_enable_global_fgcg(struct dccg *dccg, bool enable)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);

@@ -85,9 +85,18 @@ void dccg42_enable_global_fgcg(struct dccg *dccg, bool value)
         * Fine grain control via bit2 of debug flag.
         */
        if (dccg->ctx->dc->debug.disable_clock_gate || 
(dccg->ctx->dc->debug.iommu_mismatch_temp_wka & 0x4))
-               value = false;
+               enable = false;

-       REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, !value);
+       REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, 
!enable);
+}
+
+bool dccg42_get_global_fgcg_status(struct dccg *dccg)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+       uint32_t disabled = 0;
+
+       REG_GET(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, &disabled);
+       return disabled & 0x1;
 }

 void dccg42_set_physymclk(
@@ -339,7 +348,8 @@ static const struct dccg_funcs dccg42_funcs = {
        .dccg_root_gate_disable_control = dccg35_root_gate_disable_control,
        .dccg_read_reg_state = dccg31_read_reg_state,
        .dccg_enable_global_fgcg = dccg42_enable_global_fgcg,
-       .allow_clock_gating = dccg2_allow_clock_gating
+       .allow_clock_gating = dccg2_allow_clock_gating,
+       .dccg_get_global_fgcg_status = dccg42_get_global_fgcg_status,
 };

 struct dccg *dccg42_create(
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h 
b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
index a2b17ed11bdb..ebd3cec1a977 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
@@ -247,6 +247,7 @@ void dccg42_otg_add_pixel(struct dccg *dccg,
 void dccg42_otg_drop_pixel(struct dccg *dccg,
                uint32_t otg_inst);
 void dccg42_enable_global_fgcg(struct dccg *dccg, bool value);
+bool dccg42_get_global_fgcg_status(struct dccg *dccg);

 void dccg42_set_physymclk(
                struct dccg *dccg,
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 6db7c8753081..e756719308ab 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
@@ -348,6 +348,7 @@ struct dccg_funcs {
        void (*dccg_root_gate_disable_control)(struct dccg *dccg, uint32_t 
pipe_idx, uint32_t disable_clock_gating);
        void (*dccg_read_reg_state)(struct dccg *dccg, struct 
dcn_dccg_reg_state *dccg_reg_state);
        void (*dccg_enable_global_fgcg)(struct dccg *dccg, bool enable);
+       bool (*dccg_get_global_fgcg_status)(struct dccg *dccg);
 };

 #endif //__DAL_DCCG_H__
diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c 
b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
index 729c2b653161..94361e326c56 100644
--- a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
+++ b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
@@ -22,6 +22,45 @@
 #define DC_LOGGER \
        pg_cntl->ctx->logger

+/*
+ * ONO PG Workoaround: Saved FGCG repeaters states captured before powering up 
an ONO
+ * domain so it can be restored once the domain is powered up.
+ */
+struct dcn42_global_fgcg_rep_state {
+       uint32_t dmu_rep_fgcg;
+       uint32_t dccg_global_ono_rep_fgcg;
+       uint32_t az_rep_fgcg;
+};
+
+/* Save and disable FGCG repeaters before powering up the ONO domain. */
+static void pg_cntl42_save_and_disable_global_fgcg_rep(struct pg_cntl *pg_cntl,
+               struct dcn42_global_fgcg_rep_state *state)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+
+       REG_GET(DMU_CLK_CNTL, LONO_FGCG_REP_DIS, &state->dmu_rep_fgcg);
+       if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_get_global_fgcg_status)
+               state->dccg_global_ono_rep_fgcg = 
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_get_global_fgcg_status(pg_cntl->ctx->dc->res_pool->dccg);
+       REG_GET(AZ_CLOCK_CNTL, AZ_GLOBAL_FGCG_REP_DIS, &state->az_rep_fgcg);
+
+       REG_UPDATE(DMU_CLK_CNTL, LONO_FGCG_REP_DIS, 1);
+       if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 false);
+       REG_UPDATE(AZ_CLOCK_CNTL, AZ_GLOBAL_FGCG_REP_DIS, 1);
+}
+
+/* Restore FGCG repeaters after the ONO domains are powered up. */
+static void pg_cntl42_restore_global_fgcg_rep(struct pg_cntl *pg_cntl,
+               struct dcn42_global_fgcg_rep_state *state)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+
+       REG_UPDATE(DMU_CLK_CNTL, LONO_FGCG_REP_DIS, state->dmu_rep_fgcg);
+       if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 state->dccg_global_ono_rep_fgcg);
+       REG_UPDATE(AZ_CLOCK_CNTL, AZ_GLOBAL_FGCG_REP_DIS, state->az_rep_fgcg);
+}
+
 static bool pg_cntl42_dsc_pg_status(struct pg_cntl *pg_cntl, unsigned int 
dsc_inst)
 {
        struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
@@ -54,6 +93,7 @@ void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, 
unsigned int dsc_inst, bo
        uint32_t power_gate = power_on ? 0 : 1;
        uint32_t pwr_status = power_on ? 0 : 2;
        uint32_t org_ip_request_cntl = 0;
+       struct dcn42_global_fgcg_rep_state fgcg_rep_state = {0};
        bool block_enabled;

        /*need to enable dscclk regardless DSC_PG*/
@@ -81,10 +121,9 @@ void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, 
unsigned int dsc_inst, bo
        if (org_ip_request_cntl == 0)
                REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);

-       if (power_on) {
-               if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
-                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 false);
-       }
+       if (power_on)
+               pg_cntl42_save_and_disable_global_fgcg_rep(pg_cntl, 
&fgcg_rep_state);
+
        switch (dsc_inst) {
        case 0: /* DSC0 */
                REG_UPDATE(DOMAIN16_PG_CONFIG,
@@ -123,10 +162,8 @@ void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, 
unsigned int dsc_inst, bo
                break;
        }

-       if (power_on) {
-               if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
-                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 true);
-       }
+       if (power_on)
+               pg_cntl42_restore_global_fgcg_rep(pg_cntl, &fgcg_rep_state);

        if (dsc_inst < MAX_PIPES)
                pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on;
@@ -174,6 +211,7 @@ void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, 
unsigned int hubp_dp
        uint32_t power_gate = power_on ? 0 : 1;
        uint32_t pwr_status = power_on ? 0 : 2;
        uint32_t org_ip_request_cntl;
+       struct dcn42_global_fgcg_rep_state fgcg_rep_state = {0};
        bool block_enabled;
        bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg ||
                       pg_cntl->ctx->dc->debug.disable_hubp_power_gate ||
@@ -196,10 +234,8 @@ void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl 
*pg_cntl, unsigned int hubp_dp
        if (org_ip_request_cntl == 0)
                REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);

-       if (power_on) {
-               if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
-                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 false);
-       }
+       if (power_on)
+               pg_cntl42_save_and_disable_global_fgcg_rep(pg_cntl, 
&fgcg_rep_state);

        switch (hubp_dpp_inst) {
        case 0:
@@ -227,10 +263,9 @@ void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl 
*pg_cntl, unsigned int hubp_dp
                break;
        }

-       if (power_on) {
-               if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
-                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 true);
-       }
+       if (power_on)
+               pg_cntl42_restore_global_fgcg_rep(pg_cntl, &fgcg_rep_state);
+
        DC_LOG_DEBUG("HUBP DPP instance %d, power %s", hubp_dpp_inst,
                power_on ? "ON" : "OFF");

@@ -258,6 +293,7 @@ void pg_cntl42_hpo_pg_control(struct pg_cntl *pg_cntl, bool 
power_on)
        uint32_t pwr_status = power_on ? 0 : 2;
        uint32_t org_ip_request_cntl;
        uint32_t power_forceon;
+       struct dcn42_global_fgcg_rep_state fgcg_rep_state = {0};
        bool block_enabled;

        bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg ||
@@ -282,17 +318,15 @@ void pg_cntl42_hpo_pg_control(struct pg_cntl *pg_cntl, 
bool power_on)
        REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
        if (org_ip_request_cntl == 0)
                REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
-       if (power_on) {
-               if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
-                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 false);
-       }
+       if (power_on)
+               pg_cntl42_save_and_disable_global_fgcg_rep(pg_cntl, 
&fgcg_rep_state);
+
        REG_UPDATE(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
        REG_WAIT(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 
1000);

-       if (power_on) {
-               if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
-                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 true);
-       }
+       if (power_on)
+               pg_cntl42_restore_global_fgcg_rep(pg_cntl, &fgcg_rep_state);
+
        pg_cntl->pg_res_enable[PG_HPO] = power_on;
 }

@@ -466,6 +500,7 @@ void pg_cntl42_dio_pg_control(struct pg_cntl *pg_cntl, bool 
power_on)
        uint32_t power_gate = power_on ? 0 : 1;
        uint32_t pwr_status = power_on ? 0 : 2;
        uint32_t org_ip_request_cntl;
+       struct dcn42_global_fgcg_rep_state fgcg_rep_state = {0};
        bool block_enabled;

        bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg ||
@@ -486,18 +521,16 @@ void pg_cntl42_dio_pg_control(struct pg_cntl *pg_cntl, 
bool power_on)
        REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
        if (org_ip_request_cntl == 0)
                REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
-       if (power_on) {
-               if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
-                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 false);
-       }
+       if (power_on)
+               pg_cntl42_save_and_disable_global_fgcg_rep(pg_cntl, 
&fgcg_rep_state);
+
        /* DIO */
        REG_UPDATE(DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
        REG_WAIT(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 
1000);

-       if (power_on) {
-               if 
(pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
-                       
pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg,
 true);
-       }
+       if (power_on)
+               pg_cntl42_restore_global_fgcg_rep(pg_cntl, &fgcg_rep_state);
+
        pg_cntl->pg_res_enable[PG_DIO] = power_on;

 }
diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h 
b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h
index 7e8f4f03ae0e..813fa5c81172 100644
--- a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h
+++ b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h
@@ -34,7 +34,9 @@
        SR(DOMAIN24_PG_STATUS), \
        SR(DOMAIN25_PG_STATUS), \
        SR(DOMAIN26_PG_STATUS), \
-       SR(DC_IP_REQUEST_CNTL)
+       SR(DC_IP_REQUEST_CNTL), \
+       SR(DMU_CLK_CNTL), \
+       SR(AZ_CLOCK_CNTL)

 #define PG_CNTL_REG_LIST_DCN42B()\
        SR(DOMAIN0_PG_CONFIG), \
@@ -63,7 +65,9 @@
        SR(DOMAIN24_PG_STATUS), \
        SR(DOMAIN25_PG_STATUS), \
        SR(DOMAIN26_PG_STATUS), \
-       SR(DC_IP_REQUEST_CNTL)
+       SR(DC_IP_REQUEST_CNTL), \
+       SR(DMU_CLK_CNTL), \
+       SR(AZ_CLOCK_CNTL)

 #define PG_CNTL_SF(reg_name, field_name, post_fix)\
        .field_name = reg_name ## __ ## field_name ## post_fix
@@ -121,7 +125,9 @@
        PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
        PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
        PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
-       PG_CNTL_SF(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh)
+       PG_CNTL_SF(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
+       PG_CNTL_SF(DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh), \
+       PG_CNTL_SF(AZ_CLOCK_CNTL, AZ_GLOBAL_FGCG_REP_DIS, mask_sh)

 /* Not in DCN42B:
  * PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),
@@ -178,7 +184,9 @@
        PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
        PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
        PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
-       PG_CNTL_SF(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh)
+       PG_CNTL_SF(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
+       PG_CNTL_SF(DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh), \
+       PG_CNTL_SF(AZ_CLOCK_CNTL, AZ_GLOBAL_FGCG_REP_DIS, mask_sh)

 struct pg_cntl_shift {
        uint8_t IP_REQUEST_EN;
@@ -186,6 +194,8 @@ struct pg_cntl_shift {
        uint8_t DOMAIN_POWER_GATE;
        uint8_t DOMAIN_DESIRED_PWR_STATE;
        uint8_t DOMAIN_PGFSM_PWR_STATUS;
+       uint8_t LONO_FGCG_REP_DIS;
+       uint8_t AZ_GLOBAL_FGCG_REP_DIS;
 };
 struct pg_cntl_mask {
        uint32_t IP_REQUEST_EN;
@@ -193,6 +203,8 @@ struct pg_cntl_mask {
        uint32_t DOMAIN_POWER_GATE;
        uint32_t DOMAIN_DESIRED_PWR_STATE;
        uint32_t DOMAIN_PGFSM_PWR_STATUS;
+       uint32_t LONO_FGCG_REP_DIS;
+       uint32_t AZ_GLOBAL_FGCG_REP_DIS;
 };

 struct pg_cntl_registers {
@@ -224,6 +236,8 @@ struct pg_cntl_registers {
        uint32_t DOMAIN24_PG_STATUS;
        uint32_t DOMAIN25_PG_STATUS;
        uint32_t DOMAIN26_PG_STATUS;
+       uint32_t DMU_CLK_CNTL;
+       uint32_t AZ_CLOCK_CNTL;
 };

 struct dcn_pg_cntl {
--
2.54.0

Reply via email to