From 4b5e7d620901778b24a2980bbc9941eff9b47f77 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 6 Jan 2017 16:23:18 -0500 Subject: [PATCH] drm/amd/display: set blank functionality 1. remove the sleep mechanism while set_blank true from the timing generator. Since Hw sequencer is the one that manages the flow he will be responsible for wait for blanck in a critical places. Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_hw_sequencer.c | 20 ++++++++++ .../display/dc/dce110/dce110_hw_sequencer.c | 12 +++--- .../dc/dce110/dce110_timing_generator.c | 28 +------------ .../dc/dce110/dce110_timing_generator.h | 2 +- .../dc/dce110/dce110_timing_generator_v.c | 39 +++---------------- .../amd/display/dc/inc/hw/timing_generator.h | 2 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++ 7 files changed, 37 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index d5cffa51ca96..9f462a299ff3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -91,3 +91,23 @@ void color_space_to_black_color( break; } } + +bool hwss_wait_for_blank_complete( + struct timing_generator *tg) +{ + int counter; + + for (counter = 0; counter < 100; counter++) { + if (tg->funcs->is_blanked(tg)) + break; + + msleep(1); + } + + if (counter == 100) { + dm_error("DC: failed to blank crtc!\n"); + return false; + } + + return true; +} 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 7c27a820e5be..965e47a5acfa 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 @@ -623,7 +623,7 @@ static void program_scaler(const struct core_dc *dc, &pipe_ctx->scl_data); } -static enum dc_status prog_pixclk_crtc_otg( +static enum dc_status dce110_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, struct validate_context *context, struct core_dc *dc) @@ -641,6 +641,7 @@ static enum dc_status prog_pixclk_crtc_otg( pipe_ctx->tg->funcs->set_blank_color( pipe_ctx->tg, &black_color); + /* * Must blank CRTC after disabling power gating and before any * programming, otherwise CRTC will be hung in bad state @@ -1047,7 +1048,8 @@ static void reset_single_pipe_hw_ctx( struct validate_context *context) { core_link_disable_stream(pipe_ctx); - if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) { + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) { dm_error("DC: failed to blank crtc!\n"); BREAK_TO_DEBUGGER(); } @@ -1560,9 +1562,6 @@ static void update_plane_addr(const struct core_dc *dc, surface->public.flip_immediate); surface->status.requested_address = surface->public.address; - - if (surface->public.visible) - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false); } void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) @@ -1718,6 +1717,7 @@ static void init_hw(struct core_dc *dc) /* Blank controller using driver code instead of * command table. */ tg->funcs->set_blank(tg, true); + hwss_wait_for_blank_complete(tg); } for (i = 0; i < dc->res_pool->audio_count; i++) { @@ -2002,7 +2002,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_drr = set_drr, .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, - .prog_pixclk_crtc_otg = prog_pixclk_crtc_otg, + .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, }; bool dce110_hw_sequencer_construct(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index e70704d1ba87..f4b8576a0546 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1808,7 +1808,7 @@ bool dce110_tg_is_blanked(struct timing_generator *tg) return false; } -bool dce110_tg_set_blank(struct timing_generator *tg, +void dce110_tg_set_blank(struct timing_generator *tg, bool enable_blanking) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); @@ -1824,8 +1824,6 @@ bool dce110_tg_set_blank(struct timing_generator *tg, value = 0; if (enable_blanking) { - int counter; - set_reg_field_value( value, 1, @@ -1834,32 +1832,8 @@ bool dce110_tg_set_blank(struct timing_generator *tg, dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value); - for (counter = 0; counter < 100; counter++) { - value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL)); - - if (get_reg_field_value( - value, - CRTC_BLANK_CONTROL, - CRTC_BLANK_DATA_EN) == 1 && - get_reg_field_value( - value, - CRTC_BLANK_CONTROL, - CRTC_CURRENT_BLANK_STATE) == 1) - break; - - msleep(1); - } - - if (counter == 100) { - dm_logger_write(tg->ctx->logger, LOG_ERROR, - "timing generator %d blank timing out.\n", - tg110->controller_id); - return false; - } } else dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0); - - return true; } bool dce110_tg_validate_timing(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 39906502ad5c..dcb49fe452c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -257,7 +257,7 @@ void dce110_tg_program_timing(struct timing_generator *tg, bool dce110_tg_is_blanked(struct timing_generator *tg); -bool dce110_tg_set_blank(struct timing_generator *tg, +void dce110_tg_set_blank(struct timing_generator *tg, bool enable_blanking); bool dce110_tg_validate_timing(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 3bf3179e07c5..682a3de7ba48 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -72,12 +72,11 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg) return true; } -static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) +static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t value = dm_read_reg(tg->ctx, addr); - uint8_t counter = 100; set_reg_field_value( value, @@ -92,35 +91,9 @@ static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) CRTC_BLANK_DE_MODE); dm_write_reg(tg->ctx, addr, value); - - while (counter > 0) { - value = dm_read_reg(tg->ctx, addr); - - if (get_reg_field_value( - value, - CRTCV_BLANK_CONTROL, - CRTC_BLANK_DATA_EN) == 1 && - get_reg_field_value( - value, - CRTCV_BLANK_CONTROL, - CRTC_CURRENT_BLANK_STATE) == 1) - break; - - msleep(1); - counter--; - } - - if (!counter) { - dm_logger_write(tg->ctx->logger, LOG_ERROR, - "timing generator %d blank timing out.\n", - tg110->controller_id); - return false; - } - - return true; } -static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) +static void dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) { uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t value = dm_read_reg(tg->ctx, addr); @@ -138,8 +111,6 @@ static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) CRTC_BLANK_DE_MODE); dm_write_reg(tg->ctx, addr, value); - - return true; } static bool dce110_timing_generator_v_is_in_vertical_blank( @@ -429,13 +400,13 @@ static void dce110_timing_generator_v_enable_advanced_request( dm_write_reg(tg->ctx, addr, value); } -static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg, +static void dce110_timing_generator_v_set_blank(struct timing_generator *tg, bool enable_blanking) { if (enable_blanking) - return dce110_timing_generator_v_blank_crtc(tg); + dce110_timing_generator_v_blank_crtc(tg); else - return dce110_timing_generator_v_unblank_crtc(tg); + dce110_timing_generator_v_unblank_crtc(tg); } static void dce110_timing_generator_v_program_timing(struct timing_generator *tg, 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 6ac609f6f89f..baa9445833fb 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 @@ -129,7 +129,7 @@ struct timing_generator_funcs { uint32_t early_cntl); void (*wait_for_state)(struct timing_generator *tg, enum crtc_state state); - bool (*set_blank)(struct timing_generator *tg, + void (*set_blank)(struct timing_generator *tg, bool enable_blanking); bool (*is_blanked)(struct timing_generator *tg); void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color); 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 895c446cebf9..562c8978fe9c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -151,4 +151,7 @@ void color_space_to_black_color( enum dc_color_space colorspace, struct tg_color *black_color); +bool hwss_wait_for_blank_complete( + struct timing_generator *tg); + #endif /* __DC_HW_SEQUENCER_H__ */ -- 2.30.2