From 2b593b7c34424d6e62665667e89a5ea19da27457 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Tue, 5 Mar 2019 19:28:10 -0500 Subject: [PATCH 2502/2940] drm/amd/display: add global master update lock for DCN2 [why] when an update programming sequence requires both front end and back end pipe to be updated synchronously, a global update lock needs to be set to ensure that we don't get a frame with only front end update but not the back end update. [how] setup global lock parameters on enable_stream_timing. enable global lock when pipe_control_lock_global is called. disable global lock when pipe_control_lock is called. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 4 ++ .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 63 ++++++++++++++++++- .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h | 3 + .../amd/display/dc/inc/hw/timing_generator.h | 2 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 + 5 files changed, 72 insertions(+), 1 deletion(-) 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 dc34ce28505c..fbcb4d860e7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -727,6 +727,10 @@ enum dc_status dcn20_enable_stream_timing( pipe_ctx->stream->signal, true); + if (pipe_ctx->stream_res.tg->funcs->setup_global_lock) + pipe_ctx->stream_res.tg->funcs->setup_global_lock( + pipe_ctx->stream_res.tg); + /* program otg blank color */ color_space = stream->output_color_space; color_space_to_black_color(dc, color_space, &black_color); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c index 43e71b4ab5e8..ea6a19063b22 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c @@ -330,6 +330,65 @@ void optc2_triplebuffer_unlock(struct timing_generator *optc) } + +void optc2_setup_global_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t v_blank_start = 0; + uint32_t h_blank_start = 0, h_total = 0; + + REG_SET(OTG_GLOBAL_CONTROL1, 0, MASTER_UPDATE_LOCK_DB_EN, 1); + + REG_SET(OTG_GLOBAL_CONTROL2, 0, DIG_UPDATE_LOCATION, 20); + + REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, &v_blank_start); + + REG_GET(OTG_H_BLANK_START_END, OTG_H_BLANK_START, &h_blank_start); + + REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &h_total); + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_X, + h_blank_start - 200 - 1, + MASTER_UPDATE_LOCK_DB_Y, + v_blank_start - 1); +} + +void optc2_lock_global(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1); + + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + /* Should be fast, status does not update on maximus */ + if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); +} + +void optc2_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0); + + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + /* Should be fast, status does not update on maximus */ + if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); +} + void optc2_lock_doublebuffer_enable(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -424,8 +483,10 @@ static struct timing_generator_funcs dcn20_tg_funcs = { .triplebuffer_lock = optc2_triplebuffer_lock, .triplebuffer_unlock = optc2_triplebuffer_unlock, .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc1_lock, + .lock = optc2_lock, .unlock = optc1_unlock, + .lock_global = optc2_lock_global, + .setup_global_lock = optc2_setup_global_lock, .lock_doublebuffer_enable = optc2_lock_doublebuffer_enable, .lock_doublebuffer_disable = optc2_lock_doublebuffer_disable, .enable_optc_clock = optc1_enable_optc_clock, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h index d2651d846424..a21781332a06 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h @@ -104,6 +104,9 @@ void optc2_get_optc_source(struct timing_generator *optc, void optc2_triplebuffer_lock(struct timing_generator *optc); void optc2_triplebuffer_unlock(struct timing_generator *optc); +void optc2_lock(struct timing_generator *optc); +void optc2_lock_global(struct timing_generator *optc); +void optc2_setup_global_lock(struct timing_generator *optc); void optc2_lock_doublebuffer_disable(struct timing_generator *optc); void optc2_lock_doublebuffer_enable(struct timing_generator *optc); void optc2_program_manual_trigger(struct timing_generator *optc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 75314de83b3e..2dee10f7f1fe 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -184,8 +184,10 @@ struct timing_generator_funcs { bool (*did_triggered_reset_occur)(struct timing_generator *tg); void (*setup_global_swap_lock)(struct timing_generator *tg, const struct dcp_gsl_params *gsl_params); + void (*setup_global_lock)(struct timing_generator *tg); void (*unlock)(struct timing_generator *tg); void (*lock)(struct timing_generator *tg); + void (*lock_global)(struct timing_generator *tg); void (*lock_doublebuffer_disable)(struct timing_generator *tg); void (*lock_doublebuffer_enable)(struct timing_generator *tg); #if defined(CONFIG_DRM_AMD_DC_DCN2_0) 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 a0227dedbdf6..13b113d0fe19 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -205,6 +205,7 @@ struct hw_sequencer_funcs { struct dc *dc, struct pipe_ctx *pipe, bool lock); + void (*pipe_control_lock_global)( struct dc *dc, struct pipe_ctx *pipe, -- 2.17.1