Commit 7f914a62 authored by Yongqiang Sun's avatar Yongqiang Sun Committed by Alex Deucher

drm/amd/display: Apply work around for stutter.

Power on one plane after disable all the planes, for
a hw bug work around to resolve stutter efficiency issue.
Signed-off-by: default avatarYongqiang Sun <yongqiang.sun@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 950d9265
...@@ -974,7 +974,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) ...@@ -974,7 +974,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
if (context->res_ctx.pipe_ctx[i].stream == NULL || if (context->res_ctx.pipe_ctx[i].stream == NULL ||
context->res_ctx.pipe_ctx[i].plane_state == NULL) { context->res_ctx.pipe_ctx[i].plane_state == NULL) {
context->res_ctx.pipe_ctx[i].pipe_idx = i; context->res_ctx.pipe_ctx[i].pipe_idx = i;
dc->hwss.power_down_front_end(dc, &context->res_ctx.pipe_ctx[i]); dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
} }
/* 3rd param should be true, temp w/a for RV*/ /* 3rd param should be true, temp w/a for RV*/
......
...@@ -1411,7 +1411,7 @@ static void disable_vga_and_power_gate_all_controllers( ...@@ -1411,7 +1411,7 @@ static void disable_vga_and_power_gate_all_controllers(
true); true);
dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i;
dc->hwss.power_down_front_end(dc, dc->hwss.disable_plane(dc,
&dc->current_state->res_ctx.pipe_ctx[i]); &dc->current_state->res_ctx.pipe_ctx[i]);
} }
} }
...@@ -1838,7 +1838,7 @@ static void dce110_reset_hw_ctx_wrap( ...@@ -1838,7 +1838,7 @@ static void dce110_reset_hw_ctx_wrap(
if (old_clk) if (old_clk)
old_clk->funcs->cs_power_down(old_clk); old_clk->funcs->cs_power_down(old_clk);
dc->hwss.power_down_front_end(dc, pipe_ctx_old); dc->hwss.disable_plane(dc, pipe_ctx_old);
pipe_ctx_old->stream = NULL; pipe_ctx_old->stream = NULL;
} }
...@@ -2063,8 +2063,8 @@ enum dc_status dce110_apply_ctx_to_hw( ...@@ -2063,8 +2063,8 @@ enum dc_status dce110_apply_ctx_to_hw(
context, context,
dc); dc);
if (dc->hwss.power_on_front_end) if (dc->hwss.enable_plane)
dc->hwss.power_on_front_end(dc, pipe_ctx, context); dc->hwss.enable_plane(dc, pipe_ctx, context);
if (DC_OK != status) if (DC_OK != status)
return status; return status;
...@@ -2969,7 +2969,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { ...@@ -2969,7 +2969,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
.unblank_stream = dce110_unblank_stream, .unblank_stream = dce110_unblank_stream,
.enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
.enable_display_power_gating = dce110_enable_display_power_gating, .enable_display_power_gating = dce110_enable_display_power_gating,
.power_down_front_end = dce110_power_down_fe, .disable_plane = dce110_power_down_fe,
.pipe_control_lock = dce_pipe_control_lock, .pipe_control_lock = dce_pipe_control_lock,
.set_bandwidth = dce110_set_bandwidth, .set_bandwidth = dce110_set_bandwidth,
.set_drr = set_drr, .set_drr = set_drr,
......
...@@ -363,11 +363,8 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) ...@@ -363,11 +363,8 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc)
{ {
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
struct hubp *hubp = dc->res_pool->hubps[0]; struct hubp *hubp = dc->res_pool->hubps[0];
int pwr_status = 0;
REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status); if (!hws->wa_state.DEGVIDCN10_253_applied)
/* Don't need to blank if hubp is power gated*/
if (pwr_status == 2)
return; return;
hubp->funcs->set_blank(hubp, true); hubp->funcs->set_blank(hubp, true);
...@@ -378,16 +375,29 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) ...@@ -378,16 +375,29 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc)
hubp_pg_control(hws, 0, false); hubp_pg_control(hws, 0, false);
REG_SET(DC_IP_REQUEST_CNTL, 0, REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 0); IP_REQUEST_EN, 0);
hws->wa_state.DEGVIDCN10_253_applied = false;
} }
static void apply_DEGVIDCN10_253_wa(struct dc *dc) static void apply_DEGVIDCN10_253_wa(struct dc *dc)
{ {
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
struct hubp *hubp = dc->res_pool->hubps[0]; struct hubp *hubp = dc->res_pool->hubps[0];
int i;
if (dc->debug.disable_stutter) if (dc->debug.disable_stutter)
return; return;
if (!hws->wa.DEGVIDCN10_253)
return;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
if (!dc->res_pool->hubps[i]->power_gated)
return;
}
/* all pipe power gated, apply work around to enable stutter. */
REG_SET(DC_IP_REQUEST_CNTL, 0, REG_SET(DC_IP_REQUEST_CNTL, 0,
IP_REQUEST_EN, 1); IP_REQUEST_EN, 1);
...@@ -396,6 +406,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) ...@@ -396,6 +406,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc)
IP_REQUEST_EN, 0); IP_REQUEST_EN, 0);
hubp->funcs->set_hubp_blank_en(hubp, false); hubp->funcs->set_hubp_blank_en(hubp, false);
hws->wa_state.DEGVIDCN10_253_applied = true;
} }
static void bios_golden_init(struct dc *dc) static void bios_golden_init(struct dc *dc)
...@@ -592,61 +603,14 @@ static void plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) ...@@ -592,61 +603,14 @@ static void plane_atomic_disconnect(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);
if (pipe_ctx->top_pipe) {
pipe_ctx->top_pipe->bottom_pipe = NULL;
pipe_ctx->top_pipe = NULL;
pipe_ctx->stream = NULL; pipe_ctx->stream = NULL;
memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res)); memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res)); memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
} pipe_ctx->top_pipe = NULL;
if (pipe_ctx->bottom_pipe) {
pipe_ctx->bottom_pipe->top_pipe = NULL;
pipe_ctx->bottom_pipe = NULL; pipe_ctx->bottom_pipe = NULL;
}
pipe_ctx->plane_state = NULL; pipe_ctx->plane_state = NULL;
} }
/* disable HW used by plane.
* note: cannot disable until disconnect is complete */
static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
int fe_idx = pipe_ctx->pipe_idx;
struct dce_hwseq *hws = dc->hwseq;
struct hubp *hubp = dc->res_pool->hubps[fe_idx];
struct mpc *mpc = dc->res_pool->mpc;
int opp_id = hubp->opp_id;
if (opp_id == 0xf)
return;
mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id);
dc->res_pool->opps[hubp->opp_id]->mpcc_disconnect_pending[hubp->mpcc_id] = false;
/*dm_logger_write(dc->ctx->logger, LOG_ERROR,
"[debug_mpo: atomic disable finished on mpcc %d]\n",
fe_idx);*/
hubp->funcs->set_blank(hubp, true);
if (dc->debug.sanity_checks)
dcn10_verify_allow_pstate_change_high(dc);
REG_UPDATE(HUBP_CLK_CNTL[fe_idx],
HUBP_CLOCK_ENABLE, 0);
REG_UPDATE(DPP_CONTROL[fe_idx],
DPP_CLOCK_ENABLE, 0);
if (dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0)
REG_UPDATE(OPP_PIPE_CONTROL[opp_id],
OPP_PIPE_CLOCK_EN, 0);
if (dc->debug.sanity_checks)
dcn10_verify_allow_pstate_change_high(dc);
}
/* kill power to plane hw
* note: cannot power down until plane is disable
*/
static void plane_atomic_power_down(struct dc *dc, int fe_idx) static void plane_atomic_power_down(struct dc *dc, int fe_idx)
{ {
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
...@@ -665,29 +629,51 @@ static void plane_atomic_power_down(struct dc *dc, int fe_idx) ...@@ -665,29 +629,51 @@ static void plane_atomic_power_down(struct dc *dc, int fe_idx)
} }
} }
static void dcn10_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) /* disable HW used by plane.
* note: cannot disable until disconnect is complete
*/
static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
{ {
int fe_idx = pipe_ctx->pipe_idx; int fe_idx = pipe_ctx->pipe_idx;
struct timing_generator *tg = pipe_ctx->stream_res.tg; struct dce_hwseq *hws = dc->hwseq;
struct hubp *hubp = dc->res_pool->hubps[fe_idx];
struct mpc *mpc = dc->res_pool->mpc;
int opp_id = hubp->opp_id;
struct output_pixel_processor *opp;
if (tg != NULL) { if (opp_id != 0xf) {
tg->funcs->lock(tg); mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id);
opp = dc->res_pool->opps[hubp->opp_id];
opp->mpcc_disconnect_pending[hubp->mpcc_id] = false;
hubp->funcs->set_blank(hubp, true);
}
plane_atomic_disconnect(dc, pipe_ctx); REG_UPDATE(HUBP_CLK_CNTL[fe_idx],
HUBP_CLOCK_ENABLE, 0);
REG_UPDATE(DPP_CONTROL[fe_idx],
DPP_CLOCK_ENABLE, 0);
tg->funcs->unlock(tg); if (opp_id != 0xf && dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0)
REG_UPDATE(OPP_PIPE_CONTROL[opp_id],
OPP_PIPE_CLOCK_EN, 0);
if (dc->debug.sanity_checks) hubp->power_gated = true;
dcn10_verify_allow_pstate_change_high(dc);
plane_atomic_power_down(dc, fe_idx);
}
static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
if (dc->res_pool->hubps[pipe_ctx->pipe_idx]->power_gated)
return;
plane_atomic_disable(dc, pipe_ctx); plane_atomic_disable(dc, pipe_ctx);
}
plane_atomic_power_down(dc, fe_idx); apply_DEGVIDCN10_253_wa(dc);
dm_logger_write(dc->ctx->logger, LOG_DC, dm_logger_write(dc->ctx->logger, LOG_DC,
"Reset front end %d\n", "Power down front end %d\n",
fe_idx); pipe_ctx->pipe_idx);
} }
static void dcn10_init_hw(struct dc *dc) static void dcn10_init_hw(struct dc *dc)
...@@ -780,8 +766,7 @@ static void dcn10_init_hw(struct dc *dc) ...@@ -780,8 +766,7 @@ static void dcn10_init_hw(struct dc *dc)
struct timing_generator *tg = dc->res_pool->timing_generators[i]; struct timing_generator *tg = dc->res_pool->timing_generators[i];
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
plane_atomic_disable(dc, pipe_ctx); dcn10_disable_plane(dc, pipe_ctx);
plane_atomic_power_down(dc, i);
pipe_ctx->stream_res.tg = NULL; pipe_ctx->stream_res.tg = NULL;
pipe_ctx->plane_res.hubp = NULL; pipe_ctx->plane_res.hubp = NULL;
...@@ -1468,7 +1453,7 @@ static void print_rq_dlg_ttu( ...@@ -1468,7 +1453,7 @@ static void print_rq_dlg_ttu(
); );
} }
static void dcn10_power_on_fe( static void dcn10_enable_plane(
struct dc *dc, struct dc *dc,
struct pipe_ctx *pipe_ctx, struct pipe_ctx *pipe_ctx,
struct dc_state *context) struct dc_state *context)
...@@ -1480,6 +1465,8 @@ static void dcn10_power_on_fe( ...@@ -1480,6 +1465,8 @@ static void dcn10_power_on_fe(
dcn10_verify_allow_pstate_change_high(dc); dcn10_verify_allow_pstate_change_high(dc);
} }
undo_DEGVIDCN10_253_wa(dc);
power_on_plane(dc->hwseq, power_on_plane(dc->hwseq,
pipe_ctx->pipe_idx); pipe_ctx->pipe_idx);
...@@ -1946,6 +1933,8 @@ static void update_dchubp_dpp( ...@@ -1946,6 +1933,8 @@ static void update_dchubp_dpp(
&plane_state->dcc, &plane_state->dcc,
plane_state->horizontal_mirror); plane_state->horizontal_mirror);
hubp->power_gated = false;
dc->hwss.update_plane_addr(dc, pipe_ctx); dc->hwss.update_plane_addr(dc, pipe_ctx);
if (is_pipe_tree_visible(pipe_ctx)) if (is_pipe_tree_visible(pipe_ctx))
...@@ -1988,7 +1977,7 @@ static void program_all_pipe_in_tree( ...@@ -1988,7 +1977,7 @@ static void program_all_pipe_in_tree(
struct pipe_ctx *cur_pipe_ctx = struct pipe_ctx *cur_pipe_ctx =
&dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
dcn10_power_on_fe(dc, pipe_ctx, context); dcn10_enable_plane(dc, pipe_ctx, context);
/* temporary dcn1 wa: /* temporary dcn1 wa:
* watermark update requires toggle after a/b/c/d sets are programmed * watermark update requires toggle after a/b/c/d sets are programmed
...@@ -2063,7 +2052,6 @@ static void dcn10_pplib_apply_display_requirements( ...@@ -2063,7 +2052,6 @@ static void dcn10_pplib_apply_display_requirements(
static void optimize_shared_resources(struct dc *dc) static void optimize_shared_resources(struct dc *dc)
{ {
if (dc->current_state->stream_count == 0) { if (dc->current_state->stream_count == 0) {
apply_DEGVIDCN10_253_wa(dc);
/* S0i2 message */ /* S0i2 message */
dcn10_pplib_apply_display_requirements(dc, dc->current_state); dcn10_pplib_apply_display_requirements(dc, dc->current_state);
} }
...@@ -2074,10 +2062,6 @@ static void optimize_shared_resources(struct dc *dc) ...@@ -2074,10 +2062,6 @@ static void optimize_shared_resources(struct dc *dc)
static void ready_shared_resources(struct dc *dc, struct dc_state *context) static void ready_shared_resources(struct dc *dc, struct dc_state *context)
{ {
if (dc->current_state->stream_count == 0 &&
!dc->debug.disable_stutter)
undo_DEGVIDCN10_253_wa(dc);
/* S0i2 message */ /* S0i2 message */
if (dc->current_state->stream_count == 0 && if (dc->current_state->stream_count == 0 &&
context->stream_count != 0) context->stream_count != 0)
...@@ -2152,7 +2136,7 @@ static void dcn10_apply_ctx_for_surface( ...@@ -2152,7 +2136,7 @@ static void dcn10_apply_ctx_for_surface(
if (old_pipe_ctx->stream_res.tg == tg && if (old_pipe_ctx->stream_res.tg == tg &&
old_pipe_ctx->plane_res.hubp && old_pipe_ctx->plane_res.hubp &&
old_pipe_ctx->plane_res.hubp->opp_id != 0xf) { old_pipe_ctx->plane_res.hubp->opp_id != 0xf) {
dcn10_power_down_fe(dc, pipe_ctx); dcn10_disable_plane(dc, pipe_ctx);
/* /*
* power down fe will unlock when calling reset, need * power down fe will unlock when calling reset, need
* to lock it back here. Messy, need rework. * to lock it back here. Messy, need rework.
...@@ -2184,13 +2168,9 @@ static void dcn10_apply_ctx_for_surface( ...@@ -2184,13 +2168,9 @@ static void dcn10_apply_ctx_for_surface(
struct pipe_ctx *old_pipe_ctx = struct pipe_ctx *old_pipe_ctx =
&dc->current_state->res_ctx.pipe_ctx[i]; &dc->current_state->res_ctx.pipe_ctx[i];
if (removed_pipe[i]) { if (removed_pipe[i] && num_planes == 0)
plane_atomic_disable(dc, old_pipe_ctx); dcn10_disable_plane(dc, old_pipe_ctx);
if (num_planes == 0)
plane_atomic_power_down(dc, i);
} }
}
dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
"\n============== Watermark parameters ==============\n" "\n============== Watermark parameters ==============\n"
...@@ -2514,8 +2494,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { ...@@ -2514,8 +2494,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
.disable_stream = dce110_disable_stream, .disable_stream = dce110_disable_stream,
.unblank_stream = dce110_unblank_stream, .unblank_stream = dce110_unblank_stream,
.enable_display_power_gating = dcn10_dummy_display_power_gating, .enable_display_power_gating = dcn10_dummy_display_power_gating,
.power_down_front_end = dcn10_power_down_fe, .disable_plane = dcn10_disable_plane,
.power_on_front_end = dcn10_power_on_fe,
.pipe_control_lock = dcn10_pipe_control_lock, .pipe_control_lock = dcn10_pipe_control_lock,
.set_bandwidth = dcn10_set_bandwidth, .set_bandwidth = dcn10_set_bandwidth,
.reset_hw_ctx_wrap = reset_hw_ctx_wrap, .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
......
...@@ -677,6 +677,7 @@ static struct dce_hwseq *dcn10_hwseq_create( ...@@ -677,6 +677,7 @@ static struct dce_hwseq *dcn10_hwseq_create(
hws->regs = &hwseq_reg; hws->regs = &hwseq_reg;
hws->shifts = &hwseq_shift; hws->shifts = &hwseq_shift;
hws->masks = &hwseq_mask; hws->masks = &hwseq_mask;
hws->wa.DEGVIDCN10_253 = true;
} }
return hws; return hws;
} }
......
...@@ -34,9 +34,12 @@ struct hubp { ...@@ -34,9 +34,12 @@ struct hubp {
struct dc_plane_address request_address; struct dc_plane_address request_address;
struct dc_plane_address current_address; struct dc_plane_address current_address;
int inst; int inst;
/* run time states */
int opp_id; int opp_id;
int mpcc_id; int mpcc_id;
struct dc_cursor_attributes curs_attr; struct dc_cursor_attributes curs_attr;
bool power_gated;
}; };
......
...@@ -39,6 +39,11 @@ enum pipe_gating_control { ...@@ -39,6 +39,11 @@ enum pipe_gating_control {
struct dce_hwseq_wa { struct dce_hwseq_wa {
bool blnd_crtc_trigger; bool blnd_crtc_trigger;
bool DEGVIDCN10_253;
};
struct hwseq_wa_state {
bool DEGVIDCN10_253_applied;
}; };
struct dce_hwseq { struct dce_hwseq {
...@@ -47,6 +52,7 @@ struct dce_hwseq { ...@@ -47,6 +52,7 @@ struct dce_hwseq {
const struct dce_hwseq_shift *shifts; const struct dce_hwseq_shift *shifts;
const struct dce_hwseq_mask *masks; const struct dce_hwseq_mask *masks;
struct dce_hwseq_wa wa; struct dce_hwseq_wa wa;
struct hwseq_wa_state wa_state;
}; };
struct pipe_ctx; struct pipe_ctx;
...@@ -129,9 +135,9 @@ struct hw_sequencer_funcs { ...@@ -129,9 +135,9 @@ struct hw_sequencer_funcs {
struct dc_bios *dcb, struct dc_bios *dcb,
enum pipe_gating_control power_gating); enum pipe_gating_control power_gating);
void (*power_down_front_end)(struct dc *dc, struct pipe_ctx *pipe_ctx); void (*disable_plane)(struct dc *dc, struct pipe_ctx *pipe_ctx);
void (*power_on_front_end)(struct dc *dc, void (*enable_plane)(struct dc *dc,
struct pipe_ctx *pipe, struct pipe_ctx *pipe,
struct dc_state *context); struct dc_state *context);
......
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