diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index de05ad09599f..9ef671735125 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -934,6 +934,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe); + } result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); program_timing_sync(core_dc, context); @@ -1537,6 +1541,21 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } + if (update_type > UPDATE_TYPE_FAST) { + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe_ctx); + } + } + } + if (surface_count == 0) core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); 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 64f2fd0d539e..633d858caf6f 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 @@ -1739,6 +1739,7 @@ static void dcn10_apply_ctx_for_surface( mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + old_pipe_ctx->top_pipe->opp->mpcc_disconnect_pending[old_pipe_ctx->mpcc->inst] = true; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -2012,6 +2013,20 @@ static void dcn10_log_hw_state(struct core_dc *dc) */ } +static void dcn10_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +{ + int i; + for (i = 0; i < MAX_PIPES; i++) { + if (!pipe_ctx->opp || !pipe_ctx->mpcc) + continue; + + if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { + pipe_ctx->mpcc->funcs->wait_for_idle(res_pool->mpcc[i]); + pipe_ctx->opp->mpcc_disconnect_pending[i] = false; + } + } +} + static bool dcn10_dummy_display_power_gating( struct core_dc *dc, uint8_t controller_id, @@ -2085,7 +2100,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_static_screen_control = set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, - .log_hw_state = dcn10_log_hw_state + .log_hw_state = dcn10_log_hw_state, + .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 669ac4b67ea9..c2aa69deecc2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -907,10 +907,14 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask) { + int i; oppn10->base.ctx = ctx; oppn10->base.inst = inst; oppn10->base.funcs = &dcn10_opp_funcs; + for (i = 0; i < MAX_PIPES; i++) + oppn10->base.mpcc_disconnect_pending[i] = false; + oppn10->regs = regs; oppn10->opp_shift = opp_shift; oppn10->opp_mask = opp_mask; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 30177f839b8a..cc65cfdea66f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -38,10 +38,8 @@ struct core_stream; -#define MAX_PIPES 6 #define MAX_CLOCK_SOURCES 7 - /********* core_surface **********/ #define DC_SURFACE_TO_CORE(dc_surface) \ container_of(dc_surface, struct core_surface, public) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 907e0a9a8474..0212618a36be 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -32,6 +32,9 @@ /****************************************************************************** * Data types shared between different Virtual HW blocks ******************************************************************************/ + +#define MAX_PIPES 6 + struct gamma_curve { uint32_t offset; uint32_t segments_num; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 4b0c28eef352..57bdd6c8f955 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -207,6 +207,7 @@ struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; struct pwl_params regamma_params; + bool mpcc_disconnect_pending[MAX_PIPES]; const struct opp_funcs *funcs; }; 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 4c027a98cfd3..22aca5a375ae 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -156,6 +156,8 @@ struct hw_sequencer_funcs { void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); void (*log_hw_state)(struct core_dc *dc); + + void (*wait_for_mpcc_disconnect)(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); }; void color_space_to_black_color(