aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2553-drm-amd-display-Copy-stream-updates-onto-streams.patch
blob: cdbde13a31781a35d0b9cf471922bf7fd4262a42 (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
From a7c841f7e795bac26123bfc7e442308dcb281961 Mon Sep 17 00:00:00 2001
From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Date: Tue, 14 May 2019 09:19:01 -0400
Subject: [PATCH 2553/2940] drm/amd/display: Copy stream updates onto streams

[Why]
Almost every function in DC that works with stream state expects that
the current state on the stream is the one that it should be writing
out. These functions are typically triggered by specifying a particular
stream update - but the actual contents of the stream update itself
are ignored, leaving it to the DM to actually update the stream state
itself.

The problem with doing this in DM is a matter of timing. On Linux
most of this is incorrectly done in atomic check, when we actually want
it to be done during atomic commit tail while access to DC is locked.

To give an example, a commit requesting to modify color management
state for DM could come in, be rejected, but still have modified
the actual system state for the stream since it's shared memory. The
next time color management gets programmed it'll use the rejected
color management info - which might not even still be around if it's
a custom transfer function.

So a reasonable place to perform this is within DC itself and this is
the model that's currently in use for surface updates. DC can even
compare the current system state to the incoming surface update to
determine update level, something that can't currnetly be done with the
framework for stream updates.

[How]
Duplicate the framework used for surface updates for stream updates
as well. Copy all the updates after checking the update type.

Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 97 ++++++++++++++++++++++++
 1 file changed, 97 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 1b90796cb878..76f3707b7f03 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1706,6 +1706,101 @@ static void copy_surface_update_to_plane(
 			*srf_update->coeff_reduction_factor;
 }
 
+static void copy_stream_update_to_stream(struct dc *dc,
+					 struct dc_state *context,
+					 struct dc_stream_state *stream,
+					 const struct dc_stream_update *update)
+{
+	if (update == NULL || stream == NULL)
+		return;
+
+	if (update->src.height && update->src.width)
+		stream->src = update->src;
+
+	if (update->dst.height && update->dst.width)
+		stream->dst = update->dst;
+
+	if (update->out_transfer_func &&
+	    stream->out_transfer_func != update->out_transfer_func) {
+		stream->out_transfer_func->sdr_ref_white_level =
+			update->out_transfer_func->sdr_ref_white_level;
+		stream->out_transfer_func->tf = update->out_transfer_func->tf;
+		stream->out_transfer_func->type =
+			update->out_transfer_func->type;
+		memcpy(&stream->out_transfer_func->tf_pts,
+		       &update->out_transfer_func->tf_pts,
+		       sizeof(struct dc_transfer_func_distributed_points));
+	}
+
+	if (update->hdr_static_metadata)
+		stream->hdr_static_metadata = *update->hdr_static_metadata;
+
+	if (update->abm_level)
+		stream->abm_level = *update->abm_level;
+
+	if (update->periodic_interrupt0)
+		stream->periodic_interrupt0 = *update->periodic_interrupt0;
+
+	if (update->periodic_interrupt1)
+		stream->periodic_interrupt1 = *update->periodic_interrupt1;
+
+	if (update->gamut_remap)
+		stream->gamut_remap_matrix = *update->gamut_remap;
+
+	/* Note: this being updated after mode set is currently not a use case
+	 * however if it arises OCSC would need to be reprogrammed at the
+	 * minimum
+	 */
+	if (update->output_color_space)
+		stream->output_color_space = *update->output_color_space;
+
+	if (update->output_csc_transform)
+		stream->csc_color_matrix = *update->output_csc_transform;
+
+	if (update->vrr_infopacket)
+		stream->vrr_infopacket = *update->vrr_infopacket;
+
+	if (update->dpms_off)
+		stream->dpms_off = *update->dpms_off;
+
+	if (update->vsc_infopacket)
+		stream->vsc_infopacket = *update->vsc_infopacket;
+
+	if (update->vsp_infopacket)
+		stream->vsp_infopacket = *update->vsp_infopacket;
+
+	if (update->dither_option)
+		stream->dither_option = *update->dither_option;
+#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+	/* update current stream with writeback info */
+	if (update->wb_update) {
+		int i;
+
+		stream->num_wb_info = update->wb_update->num_wb_info;
+		ASSERT(stream->num_wb_info <= MAX_DWB_PIPES);
+		for (i = 0; i < stream->num_wb_info; i++)
+			stream->writeback_info[i] =
+				update->wb_update->writeback_info[i];
+	}
+#endif
+#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
+	if (update->dsc_config) {
+		struct dc_dsc_config old_dsc_cfg = stream->timing.dsc_cfg;
+		uint32_t old_dsc_enabled = stream->timing.flags.DSC;
+		uint32_t enable_dsc = (update->dsc_config->num_slices_h != 0 &&
+				       update->dsc_config->num_slices_v != 0);
+
+		stream->timing.dsc_cfg = *update->dsc_config;
+		stream->timing.flags.DSC = enable_dsc;
+		if (!dc->res_pool->funcs->validate_bandwidth(dc, context,
+							     true)) {
+			stream->timing.dsc_cfg = old_dsc_cfg;
+			stream->timing.flags.DSC = old_dsc_enabled;
+		}
+	}
+#endif
+}
+
 static void commit_planes_do_stream_update(struct dc *dc,
 		struct dc_stream_state *stream,
 		struct dc_stream_update *stream_update,
@@ -2033,6 +2128,8 @@ void dc_commit_updates_for_stream(struct dc *dc,
 		}
 	}
 
+	copy_stream_update_to_stream(dc, context, stream, stream_update);
+
 	commit_planes_for_stream(
 				dc,
 				srf_updates,
-- 
2.17.1