Commit 4b5e7d62 authored by Hersen Wu's avatar Hersen Wu Committed by Alex Deucher

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: default avatarLeon Elazar <leon.elazar@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b06b7680
...@@ -91,3 +91,23 @@ void color_space_to_black_color( ...@@ -91,3 +91,23 @@ void color_space_to_black_color(
break; 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;
}
...@@ -623,7 +623,7 @@ static void program_scaler(const struct core_dc *dc, ...@@ -623,7 +623,7 @@ static void program_scaler(const struct core_dc *dc,
&pipe_ctx->scl_data); &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 pipe_ctx *pipe_ctx,
struct validate_context *context, struct validate_context *context,
struct core_dc *dc) struct core_dc *dc)
...@@ -641,6 +641,7 @@ static enum dc_status prog_pixclk_crtc_otg( ...@@ -641,6 +641,7 @@ static enum dc_status prog_pixclk_crtc_otg(
pipe_ctx->tg->funcs->set_blank_color( pipe_ctx->tg->funcs->set_blank_color(
pipe_ctx->tg, pipe_ctx->tg,
&black_color); &black_color);
/* /*
* Must blank CRTC after disabling power gating and before any * Must blank CRTC after disabling power gating and before any
* programming, otherwise CRTC will be hung in bad state * programming, otherwise CRTC will be hung in bad state
...@@ -1047,7 +1048,8 @@ static void reset_single_pipe_hw_ctx( ...@@ -1047,7 +1048,8 @@ static void reset_single_pipe_hw_ctx(
struct validate_context *context) struct validate_context *context)
{ {
core_link_disable_stream(pipe_ctx); 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"); dm_error("DC: failed to blank crtc!\n");
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
} }
...@@ -1560,9 +1562,6 @@ static void update_plane_addr(const struct core_dc *dc, ...@@ -1560,9 +1562,6 @@ static void update_plane_addr(const struct core_dc *dc,
surface->public.flip_immediate); surface->public.flip_immediate);
surface->status.requested_address = surface->public.address; 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) void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
...@@ -1718,6 +1717,7 @@ static void init_hw(struct core_dc *dc) ...@@ -1718,6 +1717,7 @@ static void init_hw(struct core_dc *dc)
/* Blank controller using driver code instead of /* Blank controller using driver code instead of
* command table. */ * command table. */
tg->funcs->set_blank(tg, true); tg->funcs->set_blank(tg, true);
hwss_wait_for_blank_complete(tg);
} }
for (i = 0; i < dc->res_pool->audio_count; i++) { for (i = 0; i < dc->res_pool->audio_count; i++) {
...@@ -2002,7 +2002,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { ...@@ -2002,7 +2002,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
.set_drr = set_drr, .set_drr = set_drr,
.set_static_screen_control = set_static_screen_control, .set_static_screen_control = set_static_screen_control,
.reset_hw_ctx_wrap = reset_hw_ctx_wrap, .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) bool dce110_hw_sequencer_construct(struct core_dc *dc)
......
...@@ -1808,7 +1808,7 @@ bool dce110_tg_is_blanked(struct timing_generator *tg) ...@@ -1808,7 +1808,7 @@ bool dce110_tg_is_blanked(struct timing_generator *tg)
return false; return false;
} }
bool dce110_tg_set_blank(struct timing_generator *tg, void dce110_tg_set_blank(struct timing_generator *tg,
bool enable_blanking) bool enable_blanking)
{ {
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
...@@ -1824,8 +1824,6 @@ bool dce110_tg_set_blank(struct timing_generator *tg, ...@@ -1824,8 +1824,6 @@ bool dce110_tg_set_blank(struct timing_generator *tg,
value = 0; value = 0;
if (enable_blanking) { if (enable_blanking) {
int counter;
set_reg_field_value( set_reg_field_value(
value, value,
1, 1,
...@@ -1834,32 +1832,8 @@ bool dce110_tg_set_blank(struct timing_generator *tg, ...@@ -1834,32 +1832,8 @@ bool dce110_tg_set_blank(struct timing_generator *tg,
dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value); 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 } else
dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0); dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0);
return true;
} }
bool dce110_tg_validate_timing(struct timing_generator *tg, bool dce110_tg_validate_timing(struct timing_generator *tg,
......
...@@ -257,7 +257,7 @@ void dce110_tg_program_timing(struct timing_generator *tg, ...@@ -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_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 enable_blanking);
bool dce110_tg_validate_timing(struct timing_generator *tg, bool dce110_tg_validate_timing(struct timing_generator *tg,
......
...@@ -72,12 +72,11 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg) ...@@ -72,12 +72,11 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg)
return true; 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); struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t addr = mmCRTCV_BLANK_CONTROL;
uint32_t value = dm_read_reg(tg->ctx, addr); uint32_t value = dm_read_reg(tg->ctx, addr);
uint8_t counter = 100;
set_reg_field_value( set_reg_field_value(
value, value,
...@@ -92,35 +91,9 @@ static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) ...@@ -92,35 +91,9 @@ static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
CRTC_BLANK_DE_MODE); CRTC_BLANK_DE_MODE);
dm_write_reg(tg->ctx, addr, value); 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 addr = mmCRTCV_BLANK_CONTROL;
uint32_t value = dm_read_reg(tg->ctx, addr); 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) ...@@ -138,8 +111,6 @@ static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
CRTC_BLANK_DE_MODE); CRTC_BLANK_DE_MODE);
dm_write_reg(tg->ctx, addr, value); dm_write_reg(tg->ctx, addr, value);
return true;
} }
static bool dce110_timing_generator_v_is_in_vertical_blank( static bool dce110_timing_generator_v_is_in_vertical_blank(
...@@ -429,13 +400,13 @@ static void dce110_timing_generator_v_enable_advanced_request( ...@@ -429,13 +400,13 @@ static void dce110_timing_generator_v_enable_advanced_request(
dm_write_reg(tg->ctx, addr, value); 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) bool enable_blanking)
{ {
if (enable_blanking) if (enable_blanking)
return dce110_timing_generator_v_blank_crtc(tg); dce110_timing_generator_v_blank_crtc(tg);
else 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, static void dce110_timing_generator_v_program_timing(struct timing_generator *tg,
......
...@@ -129,7 +129,7 @@ struct timing_generator_funcs { ...@@ -129,7 +129,7 @@ struct timing_generator_funcs {
uint32_t early_cntl); uint32_t early_cntl);
void (*wait_for_state)(struct timing_generator *tg, void (*wait_for_state)(struct timing_generator *tg,
enum crtc_state state); enum crtc_state state);
bool (*set_blank)(struct timing_generator *tg, void (*set_blank)(struct timing_generator *tg,
bool enable_blanking); bool enable_blanking);
bool (*is_blanked)(struct timing_generator *tg); bool (*is_blanked)(struct timing_generator *tg);
void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color); void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color);
......
...@@ -151,4 +151,7 @@ void color_space_to_black_color( ...@@ -151,4 +151,7 @@ void color_space_to_black_color(
enum dc_color_space colorspace, enum dc_color_space colorspace,
struct tg_color *black_color); struct tg_color *black_color);
bool hwss_wait_for_blank_complete(
struct timing_generator *tg);
#endif /* __DC_HW_SEQUENCER_H__ */ #endif /* __DC_HW_SEQUENCER_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment