aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0988-drm-amd-dal-Fix-clock-source-remapping-issue-when-DR.patch
blob: adc167be9c142cf54a8cede5a05fef6cfcf5ffe5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
From 21ae403b786fa9b0d156f58ba2a058d72364a537 Mon Sep 17 00:00:00 2001
From: Jordan Lazare <Jordan.Lazare@amd.com>
Date: Tue, 29 Mar 2016 15:33:52 -0400
Subject: [PATCH 0988/1110] drm/amd/dal: Fix clock source remapping issue when
 DRM swaps crtcs

When disabling and enabling monitors in a specific order, eventually we'll get
to a point where the clock sources will be swapped.

BIOS appears to have an optimization where the updated phy on enable_output
doesn't take affect if it hasn't been disabled.

To fix this, reset the pipe if the clock sources change.

Signed-off-by: Jordan Lazare <Jordan.Lazare@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/core/dc.c               |   5 +-
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 114 +++++++++++----------
 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      |   2 -
 3 files changed, 61 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
index da50d25..7d234cf 100644
--- a/drivers/gpu/drm/amd/dal/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
@@ -740,10 +740,7 @@ bool dc_commit_targets(
 	}
 
 	if (result == DC_OK) {
-		core_dc->hwss.reset_hw_ctx(core_dc, context);
-
-		if (context->target_count > 0)
-			result = core_dc->hwss.apply_ctx_to_hw(core_dc, context);
+		result = core_dc->hwss.apply_ctx_to_hw(core_dc, context);
 	}
 
 	for (i = 0; i < context->target_count; i++) {
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
index a21fcbd..fa282c0 100644
--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
@@ -1224,6 +1224,43 @@ static void switch_dp_clock_sources(
  * Public functions
  ******************************************************************************/
 
+
+static void reset_single_pipe_hw_ctx(
+		const struct core_dc *dc,
+		struct pipe_ctx *pipe_ctx,
+		struct validate_context *context)
+{
+	struct dc_bios *dcb;
+
+	if (pipe_ctx->pipe_idx == DCE110_UNDERLAY_IDX)
+		return;
+
+	dcb = dal_adapter_service_get_bios_parser(
+			context->res_ctx.pool.adapter_srv);
+	if (pipe_ctx->audio) {
+		dal_audio_disable_output(pipe_ctx->audio,
+				pipe_ctx->stream_enc->id,
+				pipe_ctx->signal);
+		pipe_ctx->audio = NULL;
+	}
+
+	core_link_disable_stream(pipe_ctx);
+	if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) {
+		dm_error("DC: failed to blank crtc!\n");
+		BREAK_TO_DEBUGGER();
+	}
+	pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
+	pipe_ctx->mi->funcs->free_mem_input(
+				pipe_ctx->mi, context->target_count);
+	pipe_ctx->xfm->funcs->transform_set_scaler_bypass(pipe_ctx->xfm);
+	resource_unreference_clock_source(&context->res_ctx, pipe_ctx->clock_source);
+	dc->hwss.enable_display_power_gating(
+		pipe_ctx->stream->ctx, pipe_ctx->pipe_idx, dcb,
+			PIPE_GATING_CONTROL_ENABLE);
+
+	pipe_ctx->stream = NULL;
+}
+
 /*TODO: const validate_context*/
 static enum dc_status apply_ctx_to_hw(
 		struct core_dc *dc,
@@ -1232,6 +1269,29 @@ static enum dc_status apply_ctx_to_hw(
 	enum dc_status status;
 	uint8_t i;
 
+	/* Reset old context */
+	/* look up the targets that have been removed since last commit */
+	for (i = 0; i < MAX_PIPES; i++) {
+		struct pipe_ctx *pipe_ctx_old =
+			&dc->current_context.res_ctx.pipe_ctx[i];
+		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+		/* Note: We need to disable output if clock sources change,
+		 * since bios does optimization and doesn't apply if changing
+		 * PHY when not already disabled.
+		 */
+		if (pipe_ctx_old->stream && pipe_ctx_old->stream != pipe_ctx->stream)
+			reset_single_pipe_hw_ctx(
+				dc, pipe_ctx_old, &dc->current_context);
+		else if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
+			core_link_disable_stream(pipe_ctx);
+	}
+
+	/* Skip applying if no targets */
+	if (context->target_count <= 0)
+		return DC_OK;
+
+	/* Apply new context */
 	update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
 			true);
 
@@ -1438,59 +1498,6 @@ static void update_plane_addrs(struct core_dc *dc, struct resource_context *res_
 	}
 }
 
-static void reset_single_pipe_hw_ctx(
-		const struct core_dc *dc,
-		struct pipe_ctx *pipe_ctx,
-		struct validate_context *context)
-{
-	struct dc_bios *dcb;
-
-	if (pipe_ctx->pipe_idx == DCE110_UNDERLAY_IDX)
-		return;
-
-	dcb = dal_adapter_service_get_bios_parser(
-			context->res_ctx.pool.adapter_srv);
-	if (pipe_ctx->audio) {
-		dal_audio_disable_output(pipe_ctx->audio,
-				pipe_ctx->stream_enc->id,
-				pipe_ctx->signal);
-		pipe_ctx->audio = NULL;
-	}
-
-	core_link_disable_stream(pipe_ctx);
-	if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) {
-		dm_error("DC: failed to blank crtc!\n");
-		BREAK_TO_DEBUGGER();
-	}
-	pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
-	pipe_ctx->mi->funcs->free_mem_input(
-				pipe_ctx->mi, context->target_count);
-	pipe_ctx->xfm->funcs->transform_set_scaler_bypass(pipe_ctx->xfm);
-	resource_unreference_clock_source(&context->res_ctx, pipe_ctx->clock_source);
-	dc->hwss.enable_display_power_gating(
-		pipe_ctx->stream->ctx, pipe_ctx->pipe_idx, dcb,
-			PIPE_GATING_CONTROL_ENABLE);
-
-	pipe_ctx->stream = NULL;
-}
-
-static void reset_hw_ctx(
-		struct core_dc *dc,
-		struct validate_context *new_context)
-{
-	uint8_t i;
-
-	/* look up the targets that have been removed since last commit */
-	for (i = 0; i < MAX_PIPES; i++) {
-		struct pipe_ctx *pipe_ctx_old =
-			&dc->current_context.res_ctx.pipe_ctx[i];
-		struct pipe_ctx *pipe_ctx = &new_context->res_ctx.pipe_ctx[i];
-
-		if (pipe_ctx_old->stream && !pipe_ctx->stream)
-			reset_single_pipe_hw_ctx(
-				dc, pipe_ctx_old, &dc->current_context);
-	}
-}
 
 static void power_down(struct core_dc *dc)
 {
@@ -1643,7 +1650,6 @@ static void init_hw(struct core_dc *dc)
 static const struct hw_sequencer_funcs dce110_funcs = {
 	.init_hw = init_hw,
 	.apply_ctx_to_hw = apply_ctx_to_hw,
-	.reset_hw_ctx = reset_hw_ctx,
 	.set_plane_config = set_plane_config,
 	.update_plane_addrs = update_plane_addrs,
 	.set_gamma_correction = set_gamma_ramp,
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
index d801a60..a38c6f5 100644
--- a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
@@ -42,8 +42,6 @@ struct hw_sequencer_funcs {
 	enum dc_status (*apply_ctx_to_hw)(
 			struct core_dc *dc, struct validate_context *context);
 
-	void (*reset_hw_ctx)(struct core_dc *dc, struct validate_context *context);
-
 	void (*set_plane_config)(
 			const struct core_dc *dc,
 			struct pipe_ctx *pipe_ctx,
-- 
2.7.4