mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-23 17:46:33 -04:00
drm/amd/display: Update ONO PG Workaround for DCN42
[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 <ovidiu.bunea@amd.com> Signed-off-by: Leo Chen <leo.chen@amd.com> Signed-off-by: George Zhang <george.zhang@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user