diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2742-drm-amd-display-Apply-work-around-for-stutter.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2742-drm-amd-display-Apply-work-around-for-stutter.patch | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2742-drm-amd-display-Apply-work-around-for-stutter.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2742-drm-amd-display-Apply-work-around-for-stutter.patch new file mode 100644 index 00000000..f04b14eb --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2742-drm-amd-display-Apply-work-around-for-stutter.patch @@ -0,0 +1,432 @@ +From 554a280ac1ce62b7e2848a2b71c8aeb3ab453370 Mon Sep 17 00:00:00 2001 +From: Yongqiang Sun <yongqiang.sun@amd.com> +Date: Mon, 6 Nov 2017 14:40:31 -0500 +Subject: [PATCH 2742/4131] 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: Yongqiang Sun <yongqiang.sun@amd.com> +Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 10 +- + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 153 +++++++++------------ + .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + + drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 3 + + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 10 +- + 6 files changed, 84 insertions(+), 95 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index baab9c2..6695aa9 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -935,7 +935,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) + 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]); ++ dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]); + } + + /* 3rd param should be true, temp w/a for RV*/ +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 f6f06bc..28c977f4 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 +@@ -1413,7 +1413,7 @@ static void disable_vga_and_power_gate_all_controllers( + true); + + 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]); + } + } +@@ -1836,7 +1836,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); ++ dc->hwss.disable_plane(dc, pipe_ctx_old); + + pipe_ctx_old->stream = NULL; + } +@@ -2061,8 +2061,8 @@ enum dc_status dce110_apply_ctx_to_hw( + context, + dc); + +- if (dc->hwss.power_on_front_end) +- dc->hwss.power_on_front_end(dc, pipe_ctx, context); ++ if (dc->hwss.enable_plane) ++ dc->hwss.enable_plane(dc, pipe_ctx, context); + + if (DC_OK != status) + return status; +@@ -2967,7 +2967,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { + .unblank_stream = dce110_unblank_stream, + .enable_display_pipe_clock_gating = enable_display_pipe_clock_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, + .set_bandwidth = dce110_set_bandwidth, + .set_drr = set_drr, +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 634c553..4378811 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 +@@ -363,11 +363,8 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) + { + struct dce_hwseq *hws = dc->hwseq; + struct hubp *hubp = dc->res_pool->hubps[0]; +- int pwr_status = 0; + +- REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status); +- /* Don't need to blank if hubp is power gated*/ +- if (pwr_status == 2) ++ if (!hws->wa_state.DEGVIDCN10_253_applied) + return; + + hubp->funcs->set_blank(hubp, true); +@@ -378,16 +375,29 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) + hubp_pg_control(hws, 0, false); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); ++ ++ hws->wa_state.DEGVIDCN10_253_applied = false; + } + + static void apply_DEGVIDCN10_253_wa(struct dc *dc) + { + struct dce_hwseq *hws = dc->hwseq; + struct hubp *hubp = dc->res_pool->hubps[0]; ++ int i; + + if (dc->debug.disable_stutter) + 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, + IP_REQUEST_EN, 1); + +@@ -396,6 +406,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) + IP_REQUEST_EN, 0); + + hubp->funcs->set_hubp_blank_en(hubp, false); ++ hws->wa_state.DEGVIDCN10_253_applied = true; + } + + 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) + if (dc->debug.sanity_checks) + 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; +- 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->stream = NULL; ++ memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res)); ++ memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res)); ++ pipe_ctx->top_pipe = NULL; ++ pipe_ctx->bottom_pipe = 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) + { + struct dce_hwseq *hws = dc->hwseq; +@@ -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; +- struct timing_generator *tg = pipe_ctx->stream_res.tg; +- +- if (tg != NULL) { +- tg->funcs->lock(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; + +- plane_atomic_disconnect(dc, pipe_ctx); ++ if (opp_id != 0xf) { ++ 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); ++ } + +- tg->funcs->unlock(tg); ++ REG_UPDATE(HUBP_CLK_CNTL[fe_idx], ++ HUBP_CLOCK_ENABLE, 0); ++ REG_UPDATE(DPP_CONTROL[fe_idx], ++ DPP_CLOCK_ENABLE, 0); + +- if (dc->debug.sanity_checks) +- dcn10_verify_allow_pstate_change_high(dc); ++ 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); + +- plane_atomic_disable(dc, pipe_ctx); +- } ++ hubp->power_gated = true; + + 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); ++ ++ apply_DEGVIDCN10_253_wa(dc); + + dm_logger_write(dc->ctx->logger, LOG_DC, +- "Reset front end %d\n", +- fe_idx); ++ "Power down front end %d\n", ++ pipe_ctx->pipe_idx); + } + + 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 pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + +- plane_atomic_disable(dc, pipe_ctx); +- plane_atomic_power_down(dc, i); ++ dcn10_disable_plane(dc, pipe_ctx); + + pipe_ctx->stream_res.tg = NULL; + pipe_ctx->plane_res.hubp = NULL; +@@ -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 pipe_ctx *pipe_ctx, + struct dc_state *context) +@@ -1480,6 +1465,8 @@ static void dcn10_power_on_fe( + dcn10_verify_allow_pstate_change_high(dc); + } + ++ undo_DEGVIDCN10_253_wa(dc); ++ + power_on_plane(dc->hwseq, + pipe_ctx->pipe_idx); + +@@ -1946,6 +1933,8 @@ static void update_dchubp_dpp( + &plane_state->dcc, + plane_state->horizontal_mirror); + ++ hubp->power_gated = false; ++ + dc->hwss.update_plane_addr(dc, pipe_ctx); + + if (is_pipe_tree_visible(pipe_ctx)) +@@ -1988,7 +1977,7 @@ static void program_all_pipe_in_tree( + struct pipe_ctx *cur_pipe_ctx = + &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: + * watermark update requires toggle after a/b/c/d sets are programmed +@@ -2063,7 +2052,6 @@ static void dcn10_pplib_apply_display_requirements( + static void optimize_shared_resources(struct dc *dc) + { + if (dc->current_state->stream_count == 0) { +- apply_DEGVIDCN10_253_wa(dc); + /* S0i2 message */ + dcn10_pplib_apply_display_requirements(dc, dc->current_state); + } +@@ -2074,10 +2062,6 @@ static void optimize_shared_resources(struct dc *dc) + + 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 */ + if (dc->current_state->stream_count == 0 && + context->stream_count != 0) +@@ -2152,7 +2136,7 @@ static void dcn10_apply_ctx_for_surface( + 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); ++ dcn10_disable_plane(dc, pipe_ctx); + /* + * power down fe will unlock when calling reset, need + * to lock it back here. Messy, need rework. +@@ -2184,14 +2168,10 @@ static void dcn10_apply_ctx_for_surface( + 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); +- } ++ if (removed_pipe[i] && num_planes == 0) ++ dcn10_disable_plane(dc, old_pipe_ctx); + } + +- + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== Watermark parameters ==============\n" + "a.urgent_ns: %d \n" +@@ -2514,8 +2494,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { + .disable_stream = dce110_disable_stream, + .unblank_stream = dce110_unblank_stream, + .enable_display_power_gating = dcn10_dummy_display_power_gating, +- .power_down_front_end = dcn10_power_down_fe, +- .power_on_front_end = dcn10_power_on_fe, ++ .disable_plane = dcn10_disable_plane, + .pipe_control_lock = dcn10_pipe_control_lock, + .set_bandwidth = dcn10_set_bandwidth, + .reset_hw_ctx_wrap = reset_hw_ctx_wrap, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +index bd1a20b..6b1db2d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +@@ -677,6 +677,7 @@ static struct dce_hwseq *dcn10_hwseq_create( + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; ++ hws->wa.DEGVIDCN10_253 = true; + } + return hws; + } +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +index 3286585..49b12f6 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +@@ -34,9 +34,12 @@ struct hubp { + struct dc_plane_address request_address; + struct dc_plane_address current_address; + int inst; ++ ++ /* run time states */ + int opp_id; + int mpcc_id; + struct dc_cursor_attributes curs_attr; ++ bool power_gated; + }; + + +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 1d88526..5dc4ecf 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +@@ -39,6 +39,11 @@ enum pipe_gating_control { + + struct dce_hwseq_wa { + bool blnd_crtc_trigger; ++ bool DEGVIDCN10_253; ++}; ++ ++struct hwseq_wa_state { ++ bool DEGVIDCN10_253_applied; + }; + + struct dce_hwseq { +@@ -47,6 +52,7 @@ struct dce_hwseq { + const struct dce_hwseq_shift *shifts; + const struct dce_hwseq_mask *masks; + struct dce_hwseq_wa wa; ++ struct hwseq_wa_state wa_state; + }; + + struct pipe_ctx; +@@ -129,9 +135,9 @@ struct hw_sequencer_funcs { + struct dc_bios *dcb, + 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 dc_state *context); + +-- +2.7.4 + |