aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0725-drm-amd-dal-Fix-issue-with-pipe-powergating-sequence.patch
blob: 294bd40ebedafd93c28a7642852d35ff23faeb8e (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
From 660c54dae5f3de13f4a4ed6232575f3c598a5a6a Mon Sep 17 00:00:00 2001
From: Anthony Koo <Anthony.Koo@amd.com>
Date: Wed, 20 Jan 2016 18:16:03 -0500
Subject: [PATCH 0725/1110] drm/amd/dal: Fix issue with pipe powergating
 sequence

[Description]
It looks like pipe powergating was previously never working
properly and pipe0 was mostly always forced on.
After fixing the pipe powergating we find severe underflow
issues that is caused by bad sequence.

We need to unpowergate the pipe early, before we program
watermarks.

Signed-off-by: Anthony Koo <Anthony.Koo@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/core/dc_target.c        | 46 +++++++++++++++++++---
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 21 ++++++++--
 2 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
index a71034c..7f4f2f3 100644
--- a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
@@ -193,6 +193,34 @@ gamma_param_fail:
 	return result;
 }
 
+static bool validate_surface_address(
+		struct dc_plane_address address)
+{
+	bool is_valid_address = false;
+
+	switch (address.type) {
+	case PLN_ADDR_TYPE_GRAPHICS:
+		if (address.grph.addr.quad_part != 0)
+			is_valid_address = true;
+		break;
+	case PLN_ADDR_TYPE_GRPH_STEREO:
+		if ((address.grph_stereo.left_addr.quad_part != 0) &&
+			(address.grph_stereo.right_addr.quad_part != 0)) {
+			is_valid_address = true;
+		}
+		break;
+	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+	case PLN_ADDR_TYPE_VIDEO_INTERLACED:
+	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE_STEREO:
+	case PLN_ADDR_TYPE_VIDEO_INTERLACED_STEREO:
+	default:
+		/* not supported */
+		BREAK_TO_DEBUGGER();
+	}
+
+	return is_valid_address;
+}
+
 bool dc_commit_surfaces_to_target(
 		struct dc *dc,
 		struct dc_surface *new_surfaces[],
@@ -200,12 +228,17 @@ bool dc_commit_surfaces_to_target(
 		struct dc_target *dc_target)
 
 {
-	uint8_t i, j;
+	int i, j;
 	uint32_t prev_disp_clk = dc->current_context.bw_results.dispclk_khz;
 	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
 
-	bool current_enabled_surface_count = 0;
-	bool new_enabled_surface_count = 0;
+	int current_enabled_surface_count = 0;
+	int new_enabled_surface_count = 0;
+
+	if (!dal_adapter_service_is_in_accelerated_mode(
+						dc->res_pool.adapter_srv)) {
+		return false;
+	}
 
 	for (i = 0; i < target->status.surface_count; i++)
 		if (target->status.surfaces[i]->visible)
@@ -218,7 +251,7 @@ bool dc_commit_surfaces_to_target(
 	dal_logger_write(dc->ctx->logger,
 				LOG_MAJOR_INTERFACE_TRACE,
 				LOG_MINOR_COMPONENT_DC,
-				"%s: commit %d surfaces to target 0x%x",
+				"%s: commit %d surfaces to target 0x%x\n",
 				__func__,
 				new_surface_count,
 				dc_target);
@@ -254,6 +287,8 @@ bool dc_commit_surfaces_to_target(
 	for (i = 0; i < new_surface_count; i++) {
 		struct dc_surface *surface = new_surfaces[i];
 		struct core_surface *core_surface = DC_SURFACE_TO_CORE(surface);
+		bool is_valid_address =
+				validate_surface_address(surface->address);
 
 		dal_logger_write(dc->ctx->logger,
 					LOG_MAJOR_INTERFACE_TRACE,
@@ -269,7 +304,8 @@ bool dc_commit_surfaces_to_target(
 			core_surface,
 			target);
 
-		dc->hwss.update_plane_address(core_surface, target);
+		if (is_valid_address)
+			dc->hwss.update_plane_address(core_surface, target);
 	}
 
 	if (current_enabled_surface_count == 0 && new_enabled_surface_count > 0)
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 0eafe16..674e795 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
@@ -797,10 +797,6 @@ static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx,
 			context->res_ctx.pool.adapter_srv);
 
 	if (timing_changed) {
-		dce110_enable_display_power_gating(
-				stream->ctx, controller_idx, dcb,
-				PIPE_GATING_CONTROL_DISABLE);
-
 		/* Must blank CRTC after disabling power gating and before any
 		 * programming, otherwise CRTC will be hung in bad state
 		 */
@@ -1280,6 +1276,23 @@ static enum dc_status apply_ctx_to_hw(
 
 	update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
 			true);
+
+	for (i = 0; i < pool->controller_count; i++) {
+		struct controller_ctx *ctlr_ctx
+			= &context->res_ctx.controller_ctx[i];
+		struct dc_bios *dcb;
+
+		if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
+			continue;
+
+		dcb = dal_adapter_service_get_bios_parser(
+				context->res_ctx.pool.adapter_srv);
+
+		dce110_enable_display_power_gating(
+				dc->ctx, i, dcb,
+				PIPE_GATING_CONTROL_DISABLE);
+	}
+
 	set_safe_displaymarks(context);
 	/*TODO: when pplib works*/
 	/*dc_set_clocks_and_clock_state(context);*/
-- 
2.7.4