Skip to content

Commit

Permalink
drm/amd/display: Fix 4to1 MPC black screen with DPP RCO
Browse files Browse the repository at this point in the history
commit bf224e0 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>
  • Loading branch information
Nicholas Kazlauskas authored and gregkh committed May 17, 2023
1 parent cc99428 commit c2b2641
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 26 deletions.
12 changes: 10 additions & 2 deletions drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 */
Expand Down
8 changes: 6 additions & 2 deletions drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
13 changes: 2 additions & 11 deletions drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
23 changes: 23 additions & 0 deletions drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 10 additions & 0 deletions drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
25 changes: 14 additions & 11 deletions drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_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__
4 changes: 4 additions & 0 deletions drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit c2b2641

Please sign in to comment.