aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/core
diff options
context:
space:
mode:
authorNoah Abradjian <noah.abradjian@amd.com>2019-11-18 13:59:57 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-12-18 16:09:07 -0500
commit6b5d7730d226bed8e87085d870e76fb9018ff0b1 (patch)
treeae7b9e9dcd4341f79c40e37ed2fb6e976b92a70d /drivers/gpu/drm/amd/display/dc/core
parentdrm/amd/display: disable lttpr for RN (diff)
downloadlinux-dev-6b5d7730d226bed8e87085d870e76fb9018ff0b1.tar.xz
linux-dev-6b5d7730d226bed8e87085d870e76fb9018ff0b1.zip
drm/amd/display: Add wait for flip not pending on pipe unlock
[Why] Lack of proper timing caused intermittent underflow on unplug external DP. A previous fix was invalid and caused S0i3 regression, so had to be reverted. [How] When unlocking pipe, wait for no pipes to have flip pending before unlocking. Signed-off-by: Noah Abradjian <noah.abradjian@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 39fe38cb39b6..879cedd79d9e 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -66,6 +66,9 @@
#include "dce/dce_i2c.h"
+#define CTX \
+ dc->ctx
+
#define DC_LOGGER \
dc->ctx->logger
@@ -783,6 +786,33 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
dc_release_state(current_ctx);
}
+static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
+{
+ int i;
+ int count = 0;
+ struct pipe_ctx *pipe;
+ PERF_TRACE();
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (!pipe->plane_state)
+ continue;
+
+ /* Timeout 100 ms */
+ while (count < 100000) {
+ /* Must set to false to start with, due to OR in update function */
+ pipe->plane_state->status.is_flip_pending = false;
+ dc->hwss.update_pending_status(pipe);
+ if (!pipe->plane_state->status.is_flip_pending)
+ break;
+ udelay(1);
+ count++;
+ }
+ ASSERT(!pipe->plane_state->status.is_flip_pending);
+ }
+ PERF_TRACE();
+}
+
/*******************************************************************************
* Public functions
******************************************************************************/
@@ -1224,9 +1254,12 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc_enable_stereo(dc, context, dc_streams, context->stream_count);
- if (!dc->optimize_seamless_boot)
- /* pplib is notified if disp_num changed */
- dc->hwss.optimize_bandwidth(dc, context);
+ if (!dc->optimize_seamless_boot) {
+ /* Must wait for no flips to be pending before doing optimize bw */
+ wait_for_no_pipes_pending(dc, context);
+ /* pplib is notified if disp_num changed */
+ dc->hwss.optimize_bandwidth(dc, context);
+ }
for (i = 0; i < context->stream_count; i++)
context->streams[i]->mode_changed = false;