aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.19.8/2553-drm-amd-display-Copy-stream-updates-onto-streams.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/2553-drm-amd-display-Copy-stream-updates-onto-streams.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.19.8/2553-drm-amd-display-Copy-stream-updates-onto-streams.patch160
1 files changed, 160 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/2553-drm-amd-display-Copy-stream-updates-onto-streams.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/2553-drm-amd-display-Copy-stream-updates-onto-streams.patch
new file mode 100644
index 00000000..cdbde13a
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/2553-drm-amd-display-Copy-stream-updates-onto-streams.patch
@@ -0,0 +1,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
+