Commit 985faf2c authored by Wesley Chalmers's avatar Wesley Chalmers Committed by Alex Deucher

drm/amd/display: New sequence for HUBP blank

[WHY]
DCN30 has a bug where blanking HUBP blocks pstate allow unless
HUBP_DISABLE is toggled afterwards.

[HOW]
Create a HW sequence for blanking HUBP.
1. Wait for enter VBLANK
2. Set HUBP_BLANK
3. Make sure HUBP_IN_BLANK = 1
4. Toggle HUBP_DISABLE on and off to perform soft reset

All existing calls to hubp->funcs->set_blank should be replaced with
this new sequence.
In wait_for_mpcc_disconnect, only blank the pipe being disconnected, and
leave all other pipes unmodified.
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarWesley Chalmers <Wesley.Chalmers@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 36ec5b16
...@@ -2624,7 +2624,7 @@ static void dcn10_update_dchubp_dpp( ...@@ -2624,7 +2624,7 @@ static void dcn10_update_dchubp_dpp(
hws->funcs.update_plane_addr(dc, pipe_ctx); hws->funcs.update_plane_addr(dc, pipe_ctx);
if (is_pipe_tree_visible(pipe_ctx)) if (is_pipe_tree_visible(pipe_ctx))
hubp->funcs->set_blank(hubp, false); dc->hwss.set_hubp_blank(dc, pipe_ctx, false);
} }
void dcn10_blank_pixel_data( void dcn10_blank_pixel_data(
...@@ -3135,13 +3135,16 @@ void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) ...@@ -3135,13 +3135,16 @@ void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
return; return;
} }
static struct hubp *get_hubp_by_inst(struct resource_pool *res_pool, int mpcc_inst) static struct pipe_ctx *get_pipe_ctx_by_hubp_inst(struct dc_state *context, int mpcc_inst)
{ {
int i; int i;
for (i = 0; i < res_pool->pipe_count; i++) { for (i = 0; i < MAX_PIPES; i++) {
if (res_pool->hubps[i]->inst == mpcc_inst) if (context->res_ctx.pipe_ctx[i].plane_res.hubp
return res_pool->hubps[i]; && context->res_ctx.pipe_ctx[i].plane_res.hubp->inst == mpcc_inst) {
return &context->res_ctx.pipe_ctx[i];
}
} }
ASSERT(false); ASSERT(false);
return NULL; return NULL;
...@@ -3164,11 +3167,23 @@ void dcn10_wait_for_mpcc_disconnect( ...@@ -3164,11 +3167,23 @@ void dcn10_wait_for_mpcc_disconnect(
for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) { for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) {
if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) { if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst); struct pipe_ctx *restore_bottom_pipe;
struct pipe_ctx *restore_top_pipe;
struct pipe_ctx *inst_pipe_ctx = get_pipe_ctx_by_hubp_inst(dc->current_state, mpcc_inst);
ASSERT(inst_pipe_ctx);
res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst); res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false; pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
hubp->funcs->set_blank(hubp, true); /*
* Set top and bottom pipes NULL, as we don't want
* to blank those pipes when disconnecting from MPCC
*/
restore_bottom_pipe = inst_pipe_ctx->bottom_pipe;
restore_top_pipe = inst_pipe_ctx->top_pipe;
inst_pipe_ctx->top_pipe = inst_pipe_ctx->bottom_pipe = NULL;
dc->hwss.set_hubp_blank(dc, inst_pipe_ctx, true);
inst_pipe_ctx->top_pipe = restore_top_pipe;
inst_pipe_ctx->bottom_pipe = restore_bottom_pipe;
} }
} }
...@@ -3721,3 +3736,10 @@ void dcn10_get_clock(struct dc *dc, ...@@ -3721,3 +3736,10 @@ void dcn10_get_clock(struct dc *dc,
dc->clk_mgr->funcs->get_clock(dc->clk_mgr, context, clock_type, clock_cfg); dc->clk_mgr->funcs->get_clock(dc->clk_mgr, context, clock_type, clock_cfg);
} }
void dcn10_set_hubp_blank(const struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool blank_enable)
{
pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, blank_enable);
}
...@@ -204,5 +204,8 @@ void dcn10_wait_for_pending_cleared(struct dc *dc, ...@@ -204,5 +204,8 @@ void dcn10_wait_for_pending_cleared(struct dc *dc,
struct dc_state *context); struct dc_state *context);
void dcn10_set_hdr_multiplier(struct pipe_ctx *pipe_ctx); void dcn10_set_hdr_multiplier(struct pipe_ctx *pipe_ctx);
void dcn10_verify_allow_pstate_change_high(struct dc *dc); void dcn10_verify_allow_pstate_change_high(struct dc *dc);
void dcn10_set_hubp_blank(const struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool blank_enable);
#endif /* __DC_HWSS_DCN10_H__ */ #endif /* __DC_HWSS_DCN10_H__ */
...@@ -79,6 +79,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { ...@@ -79,6 +79,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
.set_backlight_level = dce110_set_backlight_level, .set_backlight_level = dce110_set_backlight_level,
.set_abm_immediate_disable = dce110_set_abm_immediate_disable, .set_abm_immediate_disable = dce110_set_abm_immediate_disable,
.set_pipe = dce110_set_pipe, .set_pipe = dce110_set_pipe,
.set_hubp_blank = dcn10_set_hubp_blank,
}; };
static const struct hwseq_private_funcs dcn10_private_funcs = { static const struct hwseq_private_funcs dcn10_private_funcs = {
......
...@@ -1571,7 +1571,7 @@ static void dcn20_update_dchubp_dpp( ...@@ -1571,7 +1571,7 @@ static void dcn20_update_dchubp_dpp(
if (is_pipe_tree_visible(pipe_ctx)) if (is_pipe_tree_visible(pipe_ctx))
hubp->funcs->set_blank(hubp, false); dc->hwss.set_hubp_blank(dc, pipe_ctx, false);
} }
......
...@@ -94,6 +94,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { ...@@ -94,6 +94,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = {
.optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft, .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft,
#endif #endif
.set_disp_pattern_generator = dcn20_set_disp_pattern_generator, .set_disp_pattern_generator = dcn20_set_disp_pattern_generator,
.set_hubp_blank = dcn10_set_hubp_blank,
}; };
static const struct hwseq_private_funcs dcn20_private_funcs = { static const struct hwseq_private_funcs dcn20_private_funcs = {
......
...@@ -99,6 +99,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = { ...@@ -99,6 +99,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = {
#endif #endif
.is_abm_supported = dcn21_is_abm_supported, .is_abm_supported = dcn21_is_abm_supported,
.set_disp_pattern_generator = dcn20_set_disp_pattern_generator, .set_disp_pattern_generator = dcn20_set_disp_pattern_generator,
.set_hubp_blank = dcn10_set_hubp_blank,
}; };
static const struct hwseq_private_funcs dcn21_private_funcs = { static const struct hwseq_private_funcs dcn21_private_funcs = {
......
...@@ -836,6 +836,53 @@ void dcn30_hardware_release(struct dc *dc) ...@@ -836,6 +836,53 @@ void dcn30_hardware_release(struct dc *dc)
dc->res_pool->hubbub, true, true); dc->res_pool->hubbub, true, true);
} }
void dcn30_set_hubp_blank(const struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool blank_enable)
{
struct pipe_ctx *mpcc_pipe;
struct pipe_ctx *odm_pipe;
if (blank_enable) {
struct plane_resource *plane_res = &pipe_ctx->plane_res;
struct stream_resource *stream_res = &pipe_ctx->stream_res;
/* Wait for enter vblank */
stream_res->tg->funcs->wait_for_state(stream_res->tg, CRTC_STATE_VBLANK);
/* Blank HUBP to allow p-state during blank on all timings */
pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, true);
/* Confirm hubp in blank */
ASSERT(plane_res->hubp->funcs->hubp_in_blank(plane_res->hubp));
/* Toggle HUBP_DISABLE */
plane_res->hubp->funcs->hubp_soft_reset(plane_res->hubp, true);
plane_res->hubp->funcs->hubp_soft_reset(plane_res->hubp, false);
for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) {
mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, true);
/* Confirm hubp in blank */
ASSERT(mpcc_pipe->plane_res.hubp->funcs->hubp_in_blank(mpcc_pipe->plane_res.hubp));
/* Toggle HUBP_DISABLE */
mpcc_pipe->plane_res.hubp->funcs->hubp_soft_reset(mpcc_pipe->plane_res.hubp, true);
mpcc_pipe->plane_res.hubp->funcs->hubp_soft_reset(mpcc_pipe->plane_res.hubp, false);
}
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
odm_pipe->plane_res.hubp->funcs->set_blank(odm_pipe->plane_res.hubp, true);
/* Confirm hubp in blank */
ASSERT(odm_pipe->plane_res.hubp->funcs->hubp_in_blank(odm_pipe->plane_res.hubp));
/* Toggle HUBP_DISABLE */
odm_pipe->plane_res.hubp->funcs->hubp_soft_reset(odm_pipe->plane_res.hubp, true);
odm_pipe->plane_res.hubp->funcs->hubp_soft_reset(odm_pipe->plane_res.hubp, false);
}
} else {
pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, false);
for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
odm_pipe->plane_res.hubp->funcs->set_blank(odm_pipe->plane_res.hubp, false);
}
}
void dcn30_set_disp_pattern_generator(const struct dc *dc, void dcn30_set_disp_pattern_generator(const struct dc *dc,
struct pipe_ctx *pipe_ctx, struct pipe_ctx *pipe_ctx,
enum controller_dp_test_pattern test_pattern, enum controller_dp_test_pattern test_pattern,
......
...@@ -79,4 +79,8 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc, ...@@ -79,4 +79,8 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
const struct tg_color *solid_color, const struct tg_color *solid_color,
int width, int height, int offset); int width, int height, int offset);
void dcn30_set_hubp_blank(const struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool blank_enable);
#endif /* __DC_HWSS_DCN30_H__ */ #endif /* __DC_HWSS_DCN30_H__ */
...@@ -98,6 +98,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = { ...@@ -98,6 +98,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = {
.hardware_release = dcn30_hardware_release, .hardware_release = dcn30_hardware_release,
.set_pipe = dcn21_set_pipe, .set_pipe = dcn21_set_pipe,
.set_disp_pattern_generator = dcn30_set_disp_pattern_generator, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
.set_hubp_blank = dcn30_set_hubp_blank,
}; };
static const struct hwseq_private_funcs dcn30_private_funcs = { static const struct hwseq_private_funcs dcn30_private_funcs = {
......
...@@ -98,6 +98,7 @@ static const struct hw_sequencer_funcs dcn301_funcs = { ...@@ -98,6 +98,7 @@ static const struct hw_sequencer_funcs dcn301_funcs = {
.set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
.set_pipe = dcn21_set_pipe, .set_pipe = dcn21_set_pipe,
.set_disp_pattern_generator = dcn30_set_disp_pattern_generator, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
.set_hubp_blank = dcn30_set_hubp_blank,
}; };
static const struct hwseq_private_funcs dcn301_private_funcs = { static const struct hwseq_private_funcs dcn301_private_funcs = {
......
...@@ -230,6 +230,10 @@ struct hw_sequencer_funcs { ...@@ -230,6 +230,10 @@ struct hw_sequencer_funcs {
enum dc_color_depth color_depth, enum dc_color_depth color_depth,
const struct tg_color *solid_color, const struct tg_color *solid_color,
int width, int height, int offset); int width, int height, int offset);
void (*set_hubp_blank)(const struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool blank_enable);
}; };
void color_space_to_black_color( void color_space_to_black_color(
......
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