aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2893-drm-amd-display-Implement-work-around-for-optc-under.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2893-drm-amd-display-Implement-work-around-for-optc-under.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2893-drm-amd-display-Implement-work-around-for-optc-under.patch196
1 files changed, 196 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2893-drm-amd-display-Implement-work-around-for-optc-under.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2893-drm-amd-display-Implement-work-around-for-optc-under.patch
new file mode 100644
index 00000000..81e27a18
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2893-drm-amd-display-Implement-work-around-for-optc-under.patch
@@ -0,0 +1,196 @@
+From 73b9e343583b559a3a2307957a8e9aadbaf480e4 Mon Sep 17 00:00:00 2001
+From: Yongqiang Sun <yongqiang.sun@amd.com>
+Date: Wed, 15 Nov 2017 16:21:34 -0500
+Subject: [PATCH 2893/4131] drm/amd/display: Implement work around for optc
+ underflow.
+
+Work around for a hw bug causing optc underflow if blank data
+double buffer disable and remove mpcc.
+Checking optc status after otg unlock, after wait mpcc idle
+check status again, if optc underflow just happens after wait
+mpcc idle, clear underflow status and enable blank data double
+buffer.
+
+Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com>
+Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 38 ++++++++++++++++++++--
+ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 +
+ .../amd/display/dc/dcn10/dcn10_timing_generator.c | 31 +++++++++++++-----
+ .../drm/amd/display/dc/inc/hw/timing_generator.h | 2 ++
+ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 +
+ 5 files changed, 62 insertions(+), 11 deletions(-)
+
+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 e08808b..8e2520b 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
+@@ -425,6 +425,34 @@ static void bios_golden_init(struct dc *dc)
+ }
+ }
+
++static void false_optc_underflow_wa(
++ struct dc *dc,
++ const struct dc_stream_state *stream,
++ struct timing_generator *tg)
++{
++ int i;
++ bool underflow;
++
++ if (!dc->hwseq->wa.false_optc_underflow)
++ return;
++
++ underflow = tg->funcs->is_optc_underflow_occurred(tg);
++
++ for (i = 0; i < dc->res_pool->pipe_count; i++) {
++ struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
++
++ if (old_pipe_ctx->stream != stream)
++ continue;
++
++ dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
++ }
++
++ tg->funcs->set_blank_data_double_buffer(tg, true);
++
++ if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
++ tg->funcs->clear_optc_underflow(tg);
++}
++
+ static enum dc_status dcn10_prog_pixclk_crtc_otg(
+ struct pipe_ctx *pipe_ctx,
+ struct dc_state *context,
+@@ -493,8 +521,11 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg(
+ pipe_ctx->stream_res.tg,
+ &black_color);
+
+- pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
+- hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
++ if (!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) {
++ pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
++ hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
++ false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg);
++ }
+
+ /* VTG is within DCHUB command block. DCFCLK is always on */
+ if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
+@@ -2252,6 +2283,9 @@ static void dcn10_apply_ctx_for_surface(
+
+ tg->funcs->unlock(tg);
+
++ if (num_planes == 0)
++ false_optc_underflow_wa(dc, stream, tg);
++
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *old_pipe_ctx =
+ &dc->current_state->res_ctx.pipe_ctx[i];
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+index 10cce51d..a9a5d17 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+@@ -678,6 +678,7 @@ static struct dce_hwseq *dcn10_hwseq_create(
+ hws->shifts = &hwseq_shift;
+ hws->masks = &hwseq_mask;
+ hws->wa.DEGVIDCN10_253 = true;
++ hws->wa.false_optc_underflow = true;
+ }
+ return hws;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c
+index 73ff78f..4940fdb 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c
+@@ -336,13 +336,6 @@ static void tgn10_blank_crtc(struct timing_generator *tg)
+ OTG_BLANK_DATA_EN, 1,
+ OTG_BLANK_DE_MODE, 0);
+
+- /* todo: why are we waiting for BLANK_DATA_EN? shouldn't we be waiting
+- * for status?
+- */
+- REG_WAIT(OTG_BLANK_CONTROL,
+- OTG_BLANK_DATA_EN, 1,
+- 1, 100000);
+-
+ tgn10_set_blank_data_double_buffer(tg, false);
+ }
+
+@@ -1199,14 +1192,19 @@ void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10,
+ OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status);
+ }
+
+-static void tgn10_tg_init(struct timing_generator *tg)
++static void tgn10_clear_optc_underflow(struct timing_generator *tg)
+ {
+ struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg);
+
+- tgn10_set_blank_data_double_buffer(tg, true);
+ REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1);
+ }
+
++static void tgn10_tg_init(struct timing_generator *tg)
++{
++ tgn10_set_blank_data_double_buffer(tg, true);
++ tgn10_clear_optc_underflow(tg);
++}
++
+ static bool tgn10_is_tg_enabled(struct timing_generator *tg)
+ {
+ struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg);
+@@ -1217,6 +1215,19 @@ static bool tgn10_is_tg_enabled(struct timing_generator *tg)
+ return (otg_enabled != 0);
+
+ }
++
++static bool tgn10_is_optc_underflow_occurred(struct timing_generator *tg)
++{
++ struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg);
++ uint32_t underflow_occurred = 0;
++
++ REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
++ OPTC_UNDERFLOW_OCCURRED_STATUS,
++ &underflow_occurred);
++
++ return (underflow_occurred == 1);
++}
++
+ static const struct timing_generator_funcs dcn10_tg_funcs = {
+ .validate_timing = tgn10_validate_timing,
+ .program_timing = tgn10_program_timing,
+@@ -1249,6 +1260,8 @@ static const struct timing_generator_funcs dcn10_tg_funcs = {
+ .set_blank_data_double_buffer = tgn10_set_blank_data_double_buffer,
+ .tg_init = tgn10_tg_init,
+ .is_tg_enabled = tgn10_is_tg_enabled,
++ .is_optc_underflow_occurred = tgn10_is_optc_underflow_occurred,
++ .clear_optc_underflow = tgn10_clear_optc_underflow,
+ };
+
+ void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10)
+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 8602599..e5c7e0e 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
+@@ -187,6 +187,8 @@ struct timing_generator_funcs {
+
+ void (*tg_init)(struct timing_generator *tg);
+ bool (*is_tg_enabled)(struct timing_generator *tg);
++ bool (*is_optc_underflow_occurred)(struct timing_generator *tg);
++ void (*clear_optc_underflow)(struct timing_generator *tg);
+ };
+
+ #endif
+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 5dc4ecf..0343113 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+@@ -40,6 +40,7 @@ enum pipe_gating_control {
+ struct dce_hwseq_wa {
+ bool blnd_crtc_trigger;
+ bool DEGVIDCN10_253;
++ bool false_optc_underflow;
+ };
+
+ struct hwseq_wa_state {
+--
+2.7.4
+