diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn20')
6 files changed, 89 insertions, 73 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index a444fed94184..611dac544bfe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1088,40 +1088,18 @@ void dcn20_enable_plane( // } } - -void dcn20_pipe_control_lock_global( - struct dc *dc, - struct pipe_ctx *pipe, - bool lock) -{ - if (lock) { - pipe->stream_res.tg->funcs->lock_doublebuffer_enable( - pipe->stream_res.tg); - pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg); - } else { - pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VACTIVE); - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VBLANK); - pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, - CRTC_STATE_VACTIVE); - pipe->stream_res.tg->funcs->lock_doublebuffer_disable( - pipe->stream_res.tg); - } -} - void dcn20_pipe_control_lock( struct dc *dc, struct pipe_ctx *pipe, bool lock) { bool flip_immediate = false; + bool dig_update_required = false; /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ - if (pipe->top_pipe) + if (!pipe || pipe->top_pipe) return; if (pipe->plane_state != NULL) @@ -1154,6 +1132,19 @@ void dcn20_pipe_control_lock( (!flip_immediate && pipe->stream_res.gsl_group > 0)) dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate); + if (pipe->stream && pipe->stream->update_flags.bits.dsc_changed) + dig_update_required = true; + + /* Need double buffer lock mode in order to synchronize front end pipe + * updates with dig updates. + */ + if (dig_update_required) { + if (lock) { + pipe->stream_res.tg->funcs->lock_doublebuffer_enable( + pipe->stream_res.tg); + } + } + if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) { if (lock) pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); @@ -1165,6 +1156,19 @@ void dcn20_pipe_control_lock( else pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); } + + if (dig_update_required) { + if (!lock) { + pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, + CRTC_STATE_VACTIVE); + pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, + CRTC_STATE_VBLANK); + pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, + CRTC_STATE_VACTIVE); + pipe->stream_res.tg->funcs->lock_doublebuffer_disable( + pipe->stream_res.tg); + } + } } static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe) @@ -1536,27 +1540,28 @@ static void dcn20_program_pipe( } } -static bool does_pipe_need_lock(struct pipe_ctx *pipe) -{ - if ((pipe->plane_state && pipe->plane_state->update_flags.raw) - || pipe->update_flags.raw) - return true; - if (pipe->bottom_pipe) - return does_pipe_need_lock(pipe->bottom_pipe); - - return false; -} - void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context) { - const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100; int i; struct dce_hwseq *hws = dc->hwseq; - bool pipe_locked[MAX_PIPES] = {false}; DC_LOGGER_INIT(dc->ctx->logger); + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) { + ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); + if (dc->hwss.program_triplebuffer != NULL && + !dc->debug.disable_tri_buf) { + /*turn off triple buffer for full update*/ + dc->hwss.program_triplebuffer( + dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); + } + } + } + /* Carry over GSL groups in case the context is changing. */ for (i = 0; i < dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == dc->current_state->res_ctx.pipe_ctx[i].stream) @@ -1567,17 +1572,6 @@ void dcn20_program_front_end_for_ctx( for (i = 0; i < dc->res_pool->pipe_count; i++) dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], &context->res_ctx.pipe_ctx[i]); - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (!context->res_ctx.pipe_ctx[i].top_pipe && - does_pipe_need_lock(&context->res_ctx.pipe_ctx[i])) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable) - dc->hwss.pipe_control_lock(dc, pipe_ctx, true); - if (!pipe_ctx->update_flags.bits.enable) - dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], true); - pipe_locked[i] = true; - } /* OTG blank before disabling all front ends */ for (i = 0; i < dc->res_pool->pipe_count; i++) @@ -1615,17 +1609,16 @@ void dcn20_program_front_end_for_ctx( hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context); } } +} - /* Unlock all locked pipes */ - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (pipe_locked[i]) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; +void dcn20_post_unlock_program_front_end( + struct dc *dc, + struct dc_state *context) +{ + int i; + const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100; - if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable) - dc->hwss.pipe_control_lock(dc, pipe_ctx, false); - if (!pipe_ctx->update_flags.bits.enable) - dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], false); - } + DC_LOGGER_INIT(dc->ctx->logger); for (i = 0; i < dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) @@ -1655,7 +1648,6 @@ void dcn20_program_front_end_for_ctx( dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub); } - void dcn20_prepare_bandwidth( struct dc *dc, struct dc_state *context) @@ -2306,7 +2298,8 @@ void dcn20_fpga_init_hw(struct dc *dc) REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2); REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); - REG_WRITE(REFCLK_CNTL, 0); + if (REG(REFCLK_CNTL)) + REG_WRITE(REFCLK_CNTL, 0); // diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 02c9be5ebd47..63ce763f148e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -35,6 +35,9 @@ bool dcn20_set_shaper_3dlut( void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context); +void dcn20_post_unlock_program_front_end( + struct dc *dc, + struct dc_state *context); void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx); void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx); bool dcn20_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, @@ -58,10 +61,6 @@ void dcn20_pipe_control_lock( struct dc *dc, struct pipe_ctx *pipe, bool lock); -void dcn20_pipe_control_lock_global( - struct dc *dc, - struct pipe_ctx *pipe, - bool lock); void dcn20_prepare_bandwidth( struct dc *dc, struct dc_state *context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 5e640f17d3d4..71bfde2cf646 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -33,6 +33,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, @@ -50,7 +51,8 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .disable_audio_stream = dce110_disable_audio_stream, .disable_plane = dcn20_disable_plane, .pipe_control_lock = dcn20_pipe_control_lock, - .pipe_control_lock_global = dcn20_pipe_control_lock_global, + .interdependent_update_lock = dcn10_lock_all_pipes, + .cursor_lock = dcn10_cursor_lock, .prepare_bandwidth = dcn20_prepare_bandwidth, .optimize_bandwidth = dcn20_optimize_bandwidth, .update_bandwidth = dcn20_update_bandwidth, @@ -81,6 +83,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .init_vm_ctx = dcn20_init_vm_ctx, .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, + .calc_vupdate_position = dcn10_calc_vupdate_position, }; static const struct hwseq_private_funcs dcn20_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c index de9c857ab3e9..570dfd9a243f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c @@ -545,6 +545,7 @@ const struct mpc_funcs dcn20_mpc_funcs = { .mpc_init = mpc1_mpc_init, .mpc_init_single_inst = mpc1_mpc_init_single_inst, .update_blending = mpc2_update_blending, + .cursor_lock = mpc1_cursor_lock, .get_mpcc_for_dpp = mpc2_get_mpcc_for_dpp, .wait_for_idle = mpc2_assert_idle_mpcc, .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h index c78fd5123497..496658f420db 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h @@ -179,7 +179,8 @@ SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\ SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\ SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\ - SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh) + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\ + SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh) /* * DCN2 MPC_OCSC debug status register: diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index e310d67c399a..1ba47f3a6857 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -506,6 +506,10 @@ enum dcn20_clk_src_array_id { .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ mm ## block ## id ## _ ## reg_name +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + /* NBIO */ #define NBIO_BASE_INNER(seg) \ NBIO_BASE__INST0_SEG ## seg @@ -3034,25 +3038,32 @@ validate_out: return out; } - -bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) +/* + * This must be noinline to ensure anything that deals with FP registers + * is contained within this call; previously our compiling with hard-float + * would result in fp instructions being emitted outside of the boundaries + * of the DC_FP_START/END macros, which makes sense as the compiler has no + * idea about what is wrapped and what is not + * + * This is largely just a workaround to avoid breakage introduced with 5.6, + * ideally all fp-using code should be moved into its own file, only that + * should be compiled with hard-float, and all code exported from there + * should be strictly wrapped with DC_FP_START/END + */ +static noinline bool dcn20_validate_bandwidth_fp(struct dc *dc, + struct dc_state *context, bool fast_validate) { bool voltage_supported = false; bool full_pstate_supported = false; bool dummy_pstate_supported = false; double p_state_latency_us; - DC_FP_START(); p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us; context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support = dc->debug.disable_dram_clock_change_vactive_support; if (fast_validate) { - voltage_supported = dcn20_validate_bandwidth_internal(dc, context, true); - - DC_FP_END(); - return voltage_supported; + return dcn20_validate_bandwidth_internal(dc, context, true); } // Best case, we support full UCLK switch latency @@ -3081,7 +3092,15 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, restore_dml_state: context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us; + return voltage_supported; +} +bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate) +{ + bool voltage_supported = false; + DC_FP_START(); + voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate); DC_FP_END(); return voltage_supported; } |