Commit bf224e00 authored by Nicholas Kazlauskas's avatar Nicholas Kazlauskas Committed by Alex Deucher

drm/amd/display: Fix 4to1 MPC black screen with DPP RCO

[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: stable@vger.kernel.org
Cc: Mario Limonciello <mario.limonciello@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarQingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 19914818
...@@ -726,11 +726,15 @@ void dcn10_hubp_pg_control( ...@@ -726,11 +726,15 @@ void dcn10_hubp_pg_control(
} }
} }
static void power_on_plane( static void power_on_plane_resources(
struct dce_hwseq *hws, struct dce_hwseq *hws,
int plane_id) int plane_id)
{ {
DC_LOGGER_INIT(hws->ctx->logger); 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)) { if (REG(DC_IP_REQUEST_CNTL)) {
REG_SET(DC_IP_REQUEST_CNTL, 0, REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 1); IP_REQUEST_EN, 1);
...@@ -1237,11 +1241,15 @@ void dcn10_plane_atomic_power_down(struct dc *dc, ...@@ -1237,11 +1241,15 @@ void dcn10_plane_atomic_power_down(struct dc *dc,
hws->funcs.hubp_pg_control(hws, hubp->inst, false); hws->funcs.hubp_pg_control(hws, hubp->inst, false);
dpp->funcs->dpp_reset(dpp); dpp->funcs->dpp_reset(dpp);
REG_SET(DC_IP_REQUEST_CNTL, 0, REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 0); IP_REQUEST_EN, 0);
DC_LOG_DEBUG( DC_LOG_DEBUG(
"Power gated front end %d\n", hubp->inst); "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. /* disable HW used by plane.
...@@ -2462,7 +2470,7 @@ static void dcn10_enable_plane( ...@@ -2462,7 +2470,7 @@ static void dcn10_enable_plane(
undo_DEGVIDCN10_253_wa(dc); undo_DEGVIDCN10_253_wa(dc);
power_on_plane(dc->hwseq, power_on_plane_resources(dc->hwseq,
pipe_ctx->plane_res.hubp->inst); pipe_ctx->plane_res.hubp->inst);
/* enable DCFCLK current DCHUB */ /* enable DCFCLK current DCHUB */
......
...@@ -1130,11 +1130,15 @@ void dcn20_blank_pixel_data( ...@@ -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 dce_hwseq *hws,
struct pipe_ctx *pipe_ctx) struct pipe_ctx *pipe_ctx)
{ {
DC_LOGGER_INIT(hws->ctx->logger); 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)) { if (REG(DC_IP_REQUEST_CNTL)) {
REG_SET(DC_IP_REQUEST_CNTL, 0, REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 1); IP_REQUEST_EN, 1);
...@@ -1158,7 +1162,7 @@ static void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx, ...@@ -1158,7 +1162,7 @@ static void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
//if (dc->debug.sanity_checks) { //if (dc->debug.sanity_checks) {
// dcn10_verify_allow_pstate_change_high(dc); // 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 */ /* enable DCFCLK current DCHUB */
pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true); pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
......
...@@ -66,17 +66,8 @@ void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk) ...@@ -66,17 +66,8 @@ void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
REG_UPDATE(DPPCLK_DTO_CTRL, REG_UPDATE(DPPCLK_DTO_CTRL,
DPPCLK_DTO_ENABLE[dpp_inst], 1); DPPCLK_DTO_ENABLE[dpp_inst], 1);
} else { } else {
//DTO must be enabled to generate a 0Hz clock output REG_UPDATE(DPPCLK_DTO_CTRL,
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) { DPPCLK_DTO_ENABLE[dpp_inst], 0);
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);
}
} }
dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk; dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
} }
......
...@@ -289,8 +289,31 @@ static void dccg314_set_valid_pixel_rate( ...@@ -289,8 +289,31 @@ static void dccg314_set_valid_pixel_rate(
dccg314_set_dtbclk_dto(dccg, &dto_params); 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 = { static const struct dccg_funcs dccg314_funcs = {
.update_dpp_dto = dccg31_update_dpp_dto, .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, .get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
.dccg_init = dccg31_init, .dccg_init = dccg31_init,
.set_dpstreamclk = dccg314_set_dpstreamclk, .set_dpstreamclk = dccg314_set_dpstreamclk,
......
...@@ -390,6 +390,16 @@ void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx) ...@@ -390,6 +390,16 @@ void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
pix_per_cycle); 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) void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
{ {
struct dc_context *ctx = hws->ctx; struct dc_context *ctx = hws->ctx;
......
...@@ -43,4 +43,6 @@ void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx); ...@@ -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_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__ */ #endif /* __DC_HWSS_DCN314_H__ */
...@@ -137,6 +137,7 @@ static const struct hwseq_private_funcs dcn314_private_funcs = { ...@@ -137,6 +137,7 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
.plane_atomic_disable = dcn20_plane_atomic_disable, .plane_atomic_disable = dcn20_plane_atomic_disable,
.plane_atomic_power_down = dcn10_plane_atomic_power_down, .plane_atomic_power_down = dcn10_plane_atomic_power_down,
.enable_power_gating_plane = dcn314_enable_power_gating_plane, .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, .hubp_pg_control = dcn314_hubp_pg_control,
.program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree,
.update_odm = dcn314_update_odm, .update_odm = dcn314_update_odm,
......
...@@ -148,18 +148,21 @@ struct dccg_funcs { ...@@ -148,18 +148,21 @@ struct dccg_funcs {
struct dccg *dccg, struct dccg *dccg,
int inst); int inst);
void (*set_pixel_rate_div)( void (*set_pixel_rate_div)(struct dccg *dccg,
struct dccg *dccg, uint32_t otg_inst,
uint32_t otg_inst, enum pixel_rate_div k1,
enum pixel_rate_div k1, enum pixel_rate_div k2);
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_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__ #endif //__DAL_DCCG_H__
...@@ -115,6 +115,10 @@ struct hwseq_private_funcs { ...@@ -115,6 +115,10 @@ struct hwseq_private_funcs {
void (*plane_atomic_disable)(struct dc *dc, struct pipe_ctx *pipe_ctx); void (*plane_atomic_disable)(struct dc *dc, struct pipe_ctx *pipe_ctx);
void (*enable_power_gating_plane)(struct dce_hwseq *hws, void (*enable_power_gating_plane)(struct dce_hwseq *hws,
bool enable); 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, void (*dpp_pg_control)(struct dce_hwseq *hws,
unsigned int dpp_inst, unsigned int dpp_inst,
bool power_on); bool power_on);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment