drm/amd/display: Fix 4to1 MPC black screen with DPP RCO
commit bf224e00a9f54e2bf14b4d720a09c3d2f4aa4aa8 upstream. [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: Jun Lei <Jun.Lei@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
cc9942840a
commit
c2b2641ecb
@ -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.
|
||||
@ -2450,7 +2458,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 */
|
||||
|
@ -1087,11 +1087,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);
|
||||
@ -1115,7 +1119,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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -392,6 +392,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;
|
||||
|
@ -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__ */
|
||||
|
@ -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,
|
||||
|
@ -148,18 +148,21 @@ 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_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_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__
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user