From: Yongqiang Sun <yongqiang.sun@xxxxxxx> There are different code to disable front end, it is difficult to debug and adding new process. This refactor makes all disable front end call the same functions. Change-Id: Ia88b26851bcea426104a8dd9093b912d03424c9a Signed-off-by: Yongqiang Sun <yongqiang.sun at amd.com> Reviewed-by: Tony Cheng <Tony.Cheng at amd.com> Acked-by: Harry Wentland <harry.wentland at amd.com> --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 3 + drivers/gpu/drm/amd/display/dc/core/dc.c | 15 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 10 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 262 +++++++++++---------- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- 5 files changed, 154 insertions(+), 138 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6d64a069648e..88a004cc2690 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1064,6 +1064,9 @@ bool dcn_validate_bandwidth( hsplit_pipe->stream = NULL; hsplit_pipe->top_pipe = NULL; hsplit_pipe->bottom_pipe = NULL; + /* Clear plane_res and stream_res */ + memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res)); + memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res)); resource_build_scaling_params(pipe); } /* for now important to do this after pipe split for building e2e params */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6219dd000049..16d645d6da25 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -924,9 +924,11 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); for (i = 0; i < dc->res_pool->pipe_count; i++) - if (context->res_ctx.pipe_ctx[i].stream == NULL - || context->res_ctx.pipe_ctx[i].plane_state == NULL) - dc->hwss.power_down_front_end(dc, i); + if (context->res_ctx.pipe_ctx[i].stream == NULL || + context->res_ctx.pipe_ctx[i].plane_state == NULL) { + context->res_ctx.pipe_ctx[i].pipe_idx = i; + dc->hwss.power_down_front_end(dc, &context->res_ctx.pipe_ctx[i]); + } /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -1300,8 +1302,11 @@ static void commit_planes_for_stream(struct dc *dc, if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) continue; - if (!pipe_ctx->top_pipe && pipe_ctx->stream) { - struct dc_stream_status *stream_status = stream_get_status(context, pipe_ctx->stream); + if (!pipe_ctx->top_pipe && + pipe_ctx->stream && + pipe_ctx->stream == stream) { + struct dc_stream_status *stream_status = + stream_get_status(context, pipe_ctx->stream); dc->hwss.apply_ctx_for_surface( dc, pipe_ctx->stream, stream_status->plane_count, context); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 4135de2d7203..a50e24f95ca9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1466,7 +1466,9 @@ static void disable_vga_and_power_gate_all_controllers( enable_display_pipe_clock_gating(ctx, true); - dc->hwss.power_down_front_end(dc, i); + dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i; + dc->hwss.power_down_front_end(dc, + &dc->current_state->res_ctx.pipe_ctx[i]); } } @@ -1888,7 +1890,7 @@ static void dce110_reset_hw_ctx_wrap( if (old_clk) old_clk->funcs->cs_power_down(old_clk); - dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); + dc->hwss.power_down_front_end(dc, pipe_ctx_old); pipe_ctx_old->stream = NULL; } @@ -2948,8 +2950,10 @@ static void dce110_apply_ctx_for_surface( } } -static void dce110_power_down_fe(struct dc *dc, int fe_idx) +static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) { + int fe_idx = pipe_ctx->pipe_idx; + /* Do not power down fe when stream is active on dce*/ if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) return; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2496a54c998d..9def1038ddce 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -558,13 +558,15 @@ void dcn10_verify_allow_pstate_change_high(struct dc *dc) } /* trigger HW to start disconnect plane from stream on the next vsync */ -static void plane_atomic_disconnect(struct dc *dc, - int fe_idx) +static void plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) { + int fe_idx = pipe_ctx->pipe_idx; struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; int opp_id, z_idx; int mpcc_id = -1; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + struct dce_hwseq *hws = dc->hwseq; /* look at tree rather than mi here to know if we already reset */ for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) { @@ -583,29 +585,56 @@ static void plane_atomic_disconnect(struct dc *dc, if (opp_id == dc->res_pool->pipe_count) return; - if (dc->debug.sanity_checks) - dcn10_verify_allow_pstate_change_high(dc); - hubp->funcs->dcc_control(hubp, false, false); + mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree), + dc->res_pool->opps[opp_id]->inst, fe_idx); + + if (hubp->funcs->hubp_disconnect) + hubp->funcs->hubp_disconnect(hubp); + if (dc->debug.sanity_checks) dcn10_verify_allow_pstate_change_high(dc); - mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree), - dc->res_pool->opps[opp_id]->inst, fe_idx); + if (pipe_ctx->top_pipe) { + pipe_ctx->top_pipe->bottom_pipe = NULL; + pipe_ctx->top_pipe = NULL; + pipe_ctx->stream = NULL; + memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res)); + memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res)); + } + + if (pipe_ctx->bottom_pipe) { + pipe_ctx->bottom_pipe->top_pipe = NULL; + pipe_ctx->bottom_pipe = NULL; + } + pipe_ctx->plane_state = NULL; + + /* TODO: Move to tg. */ + REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], + VUPDATE_NO_LOCK_EVENT_CLEAR, 1); } /* disable HW used by plane. * note: cannot disable until disconnect is complete */ -static void plane_atomic_disable(struct dc *dc, - int fe_idx) +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; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + + if (tg == NULL) + return; if (opp_id == 0xf) return; + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], + VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, + 1, 100000); + 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, @@ -630,62 +659,52 @@ static void plane_atomic_disable(struct dc *dc, dcn10_verify_allow_pstate_change_high(dc); } -static void reset_front_end( - struct dc *dc, - int fe_idx) +/* 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) { struct dce_hwseq *hws = dc->hwseq; - struct timing_generator *tg; - int opp_id = dc->res_pool->hubps[fe_idx]->opp_id; + struct dpp *dpp = dc->res_pool->dpps[fe_idx]; - /*Already reset*/ - if (opp_id == 0xf) - return; + if (REG(DC_IP_REQUEST_CNTL)) { + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, fe_idx, false); + hubp_pg_control(hws, fe_idx, false); + dpp->funcs->dpp_reset(dpp); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(dc->ctx->logger, LOG_DEBUG, + "Power gated front end %d\n", fe_idx); + } +} - tg = dc->res_pool->timing_generators[opp_id]; - tg->funcs->lock(tg); +static void dcn10_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + int fe_idx = pipe_ctx->pipe_idx; + struct timing_generator *tg = pipe_ctx->stream_res.tg; - plane_atomic_disconnect(dc, fe_idx); + if (tg != NULL) { + tg->funcs->lock(tg); - REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); - tg->funcs->unlock(tg); + plane_atomic_disconnect(dc, pipe_ctx); - if (dc->debug.sanity_checks) - dcn10_verify_allow_pstate_change_high(dc); + tg->funcs->unlock(tg); - if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) - REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], - VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, - 1, 100000); + if (dc->debug.sanity_checks) + dcn10_verify_allow_pstate_change_high(dc); - plane_atomic_disable(dc, fe_idx); + plane_atomic_disable(dc, pipe_ctx); + } + + plane_atomic_power_down(dc, fe_idx); dm_logger_write(dc->ctx->logger, LOG_DC, "Reset front end %d\n", fe_idx); } -static void dcn10_power_down_fe(struct dc *dc, int fe_idx) -{ - struct dce_hwseq *hws = dc->hwseq; - struct dpp *dpp = dc->res_pool->dpps[fe_idx]; - - reset_front_end(dc, fe_idx); - - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dpp_pg_control(hws, fe_idx, false); - hubp_pg_control(hws, fe_idx, false); - dpp->funcs->dpp_reset(dpp); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DEBUG, - "Power gated front end %d\n", fe_idx); - - if (dc->debug.sanity_checks) - dcn10_verify_allow_pstate_change_high(dc); -} - static void dcn10_init_hw(struct dc *dc) { int i; @@ -744,7 +763,7 @@ static void dcn10_init_hw(struct dc *dc) tg->funcs->set_blank(tg, true); hwss_wait_for_blank_complete(tg); - dcn10_power_down_fe(dc, i); + plane_atomic_power_down(dc, i); tg->funcs->tg_init(tg); } @@ -1988,8 +2007,6 @@ static void program_all_pipe_in_tree( dcn10_verify_allow_pstate_change_high(dc); } - pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); - pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; @@ -2097,62 +2114,75 @@ static void ready_shared_resources(struct dc *dc, struct dc_state *context) dcn10_pplib_apply_display_requirements(dc, context); } +static struct pipe_ctx *find_top_pipe_for_stream( + struct dc *dc, + struct dc_state *context, + const struct dc_stream_state *stream) +{ + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) + continue; + + if (pipe_ctx->stream != stream) + continue; + + if (!pipe_ctx->top_pipe) + return pipe_ctx; + } + return NULL; +} + static void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, int num_planes, struct dc_state *context) { - int i, be_idx; + int i; + struct timing_generator *tg; + bool removed_pipe[4] = { false }; + + struct pipe_ctx *top_pipe_to_program = + find_top_pipe_for_stream(dc, context, stream); + + if (!top_pipe_to_program) + return; + + tg = top_pipe_to_program->stream_res.tg; if (dc->debug.sanity_checks) dcn10_verify_allow_pstate_change_high(dc); - be_idx = -1; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (stream == context->res_ctx.pipe_ctx[i].stream) { - be_idx = context->res_ctx.pipe_ctx[i].stream_res.tg->inst; - break; - } - } - - ASSERT(be_idx != -1); + tg->funcs->lock(tg); if (num_planes == 0) { - for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { - struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) { - old_pipe_ctx->stream_res.tg->funcs->set_blank(old_pipe_ctx->stream_res.tg, true); - dcn10_power_down_fe(dc, old_pipe_ctx->pipe_idx); - } - } - return; + /* OTG blank before remove all front end */ + tg->funcs->set_blank(tg, true); } - /* reset unused mpcc */ + /* Disconnect unused mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - struct hubp *hubp = dc->res_pool->hubps[i]; - - if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) - continue; - - if (pipe_ctx->stream_res.tg && - pipe_ctx->stream_res.tg->inst == be_idx && - !pipe_ctx->top_pipe) - pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); - /* * Powergate reused pipes that are not powergated * fairly hacky right now, using opp_id as indicator + * TODO: After move dc_post to dc_update, this will + * be removed. */ - if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->plane_res.hubp->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { - dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); + if (old_pipe_ctx->stream_res.tg == tg && + old_pipe_ctx->plane_res.hubp && + old_pipe_ctx->plane_res.hubp->opp_id != 0xf) { + dcn10_power_down_fe(dc, pipe_ctx); /* * power down fe will unlock when calling reset, need * to lock it back here. Messy, need rework. @@ -2161,39 +2191,12 @@ static void dcn10_apply_ctx_for_surface( } } + if (!pipe_ctx->plane_state && + old_pipe_ctx->plane_state && + old_pipe_ctx->stream_res.tg == tg) { - if ((!pipe_ctx->plane_state && old_pipe_ctx->plane_state) - || (!pipe_ctx->stream && old_pipe_ctx->stream)) { - if (old_pipe_ctx->stream_res.tg->inst != be_idx) - continue; - - if (!old_pipe_ctx->top_pipe) { - ASSERT(0); - continue; - } - - /* reset mpc */ - dc->res_pool->mpc->funcs->remove( - dc->res_pool->mpc, - &(old_pipe_ctx->stream_res.opp->mpc_tree), - old_pipe_ctx->stream_res.opp->inst, - old_pipe_ctx->pipe_idx); - old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.hubp->mpcc_id] = true; - - /*dm_logger_write(dc->ctx->logger, LOG_ERROR, - "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", - old_pipe_ctx->mpcc->inst);*/ - - if (hubp->funcs->hubp_disconnect) - hubp->funcs->hubp_disconnect(hubp); - - if (dc->debug.sanity_checks) - dcn10_verify_allow_pstate_change_high(dc); - - old_pipe_ctx->top_pipe = NULL; - old_pipe_ctx->bottom_pipe = NULL; - old_pipe_ctx->plane_state = NULL; - old_pipe_ctx->stream = NULL; + plane_atomic_disconnect(dc, old_pipe_ctx); + removed_pipe[i] = true; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset mpcc for pipe %d\n", @@ -2201,23 +2204,24 @@ static void dcn10_apply_ctx_for_surface( } } - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + if (num_planes > 0) + program_all_pipe_in_tree(dc, top_pipe_to_program, context); + + tg->funcs->unlock(tg); - if (pipe_ctx->stream != stream) - continue; - /* looking for top pipe to program */ - if (!pipe_ctx->top_pipe) { - program_all_pipe_in_tree(dc, pipe_ctx, context); - if (pipe_ctx->stream_res.tg && - pipe_ctx->stream_res.tg->inst == be_idx && - (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) - pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg); + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *old_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[i]; + + if (removed_pipe[i]) { + plane_atomic_disable(dc, old_pipe_ctx); + if (num_planes == 0) + plane_atomic_power_down(dc, i); } } + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, "\n============== Watermark parameters ==============\n" "a.urgent_ns: %d \n" diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index f3c5468854bd..19cfca91bb4e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -129,7 +129,7 @@ struct hw_sequencer_funcs { struct dc_bios *dcb, enum pipe_gating_control power_gating); - void (*power_down_front_end)(struct dc *dc, int fe_idx); + void (*power_down_front_end)(struct dc *dc, struct pipe_ctx *pipe_ctx); void (*power_on_front_end)(struct dc *dc, struct pipe_ctx *pipe, -- 2.14.1