diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/1307-drm-amd-display-Make-stream-commits-call-into-DC-onl.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/1307-drm-amd-display-Make-stream-commits-call-into-DC-onl.patch | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/1307-drm-amd-display-Make-stream-commits-call-into-DC-onl.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/1307-drm-amd-display-Make-stream-commits-call-into-DC-onl.patch new file mode 100644 index 00000000..e6cb85c6 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/1307-drm-amd-display-Make-stream-commits-call-into-DC-onl.patch @@ -0,0 +1,273 @@ +From b3d57bb8aa9475e670ea539fb5cccf53b62f4772 Mon Sep 17 00:00:00 2001 +From: David Francis <David.Francis@amd.com> +Date: Wed, 6 Feb 2019 13:44:33 -0500 +Subject: [PATCH 1307/2940] drm/amd/display: Make stream commits call into DC + only once + +[Why] +dc_commit_updates_for_stream is called twice per stream: once +with the flip data and once will all other data. This causes +problems when these DC calls have different numbers of planes + +For example, a commit with a pageflip on plane A and a +non-pageflip change on plane B will first call +into DC with just plane A, causing plane B to be +disabled. Then it will call into DC with both planes, +re-enabling plane B + +[How] +Merge flip and full into a single bundle + +Apart from the single DC call, the logic should not be +changed by this patch + +Signed-off-by: David Francis <David.Francis@amd.com> +Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> +Acked-by: Leo Li <sunpeng.li@amd.com> +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 129 ++++++++---------- + 1 file changed, 54 insertions(+), 75 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 1b56da5a32d4..ab4bae386772 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -4758,30 +4758,25 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); + struct dm_crtc_state *dm_old_crtc_state = + to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc)); +- int flip_count = 0, planes_count = 0, vpos, hpos; ++ int planes_count = 0, vpos, hpos; + unsigned long flags; + struct amdgpu_bo *abo; + uint64_t tiling_flags, dcc_address; + uint32_t target, target_vblank; +- +- struct { +- struct dc_surface_update surface_updates[MAX_SURFACES]; +- struct dc_flip_addrs flip_addrs[MAX_SURFACES]; +- struct dc_stream_update stream_update; +- } *flip; ++ bool pflip_present = false; + + struct { + struct dc_surface_update surface_updates[MAX_SURFACES]; + struct dc_plane_info plane_infos[MAX_SURFACES]; + struct dc_scaling_info scaling_infos[MAX_SURFACES]; ++ struct dc_flip_addrs flip_addrs[MAX_SURFACES]; + struct dc_stream_update stream_update; +- } *full; ++ } *bundle; + +- flip = kzalloc(sizeof(*flip), GFP_KERNEL); +- full = kzalloc(sizeof(*full), GFP_KERNEL); ++ bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); + +- if (!flip || !full) { +- dm_error("Failed to allocate update bundles\n"); ++ if (!bundle) { ++ dm_error("Failed to allocate update bundle\n"); + goto cleanup; + } + +@@ -4791,7 +4786,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, + struct drm_crtc_state *new_crtc_state; + struct drm_framebuffer *fb = new_plane_state->fb; + struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); +- bool pflip_needed; ++ bool framebuffer_changed; + struct dc_plane_state *dc_plane; + struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state); + +@@ -4806,12 +4801,14 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, + if (!new_crtc_state->active) + continue; + +- pflip_needed = old_plane_state->fb && ++ dc_plane = dm_new_plane_state->dc_state; ++ ++ framebuffer_changed = old_plane_state->fb && + old_plane_state->fb != new_plane_state->fb; + +- dc_plane = dm_new_plane_state->dc_state; ++ pflip_present = pflip_present || framebuffer_changed; + +- if (pflip_needed) { ++ if (framebuffer_changed) { + /* + * TODO This might fail and hence better not used, wait + * explicitly on fences instead +@@ -4840,22 +4837,22 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, + + amdgpu_bo_unreserve(abo); + +- flip->flip_addrs[flip_count].address.grph.addr.low_part = lower_32_bits(afb->address); +- flip->flip_addrs[flip_count].address.grph.addr.high_part = upper_32_bits(afb->address); ++ bundle->flip_addrs[planes_count].address.grph.addr.low_part = lower_32_bits(afb->address); ++ bundle->flip_addrs[planes_count].address.grph.addr.high_part = upper_32_bits(afb->address); + + dcc_address = get_dcc_address(afb->address, tiling_flags); +- flip->flip_addrs[flip_count].address.grph.meta_addr.low_part = lower_32_bits(dcc_address); +- flip->flip_addrs[flip_count].address.grph.meta_addr.high_part = upper_32_bits(dcc_address); ++ bundle->flip_addrs[planes_count].address.grph.meta_addr.low_part = lower_32_bits(dcc_address); ++ bundle->flip_addrs[planes_count].address.grph.meta_addr.high_part = upper_32_bits(dcc_address); + +- flip->flip_addrs[flip_count].flip_immediate = ++ bundle->flip_addrs[planes_count].flip_immediate = + (crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + + timestamp_ns = ktime_get_ns(); +- flip->flip_addrs[flip_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000); +- flip->surface_updates[flip_count].flip_addr = &flip->flip_addrs[flip_count]; +- flip->surface_updates[flip_count].surface = dc_plane; ++ bundle->flip_addrs[planes_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000); ++ bundle->surface_updates[planes_count].flip_addr = &bundle->flip_addrs[planes_count]; ++ bundle->surface_updates[planes_count].surface = dc_plane; + +- if (!flip->surface_updates[flip_count].surface) { ++ if (!bundle->surface_updates[planes_count].surface) { + DRM_ERROR("No surface for CRTC: id=%d\n", + acrtc_attach->crtc_id); + continue; +@@ -4867,53 +4864,45 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, + acrtc_state, + acrtc_state->stream, + dc_plane, +- flip->flip_addrs[flip_count].flip_timestamp_in_us); ++ bundle->flip_addrs[planes_count].flip_timestamp_in_us); + + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x\n", + __func__, +- flip->flip_addrs[flip_count].address.grph.addr.high_part, +- flip->flip_addrs[flip_count].address.grph.addr.low_part); +- +- flip_count += 1; ++ bundle->flip_addrs[planes_count].address.grph.addr.high_part, ++ bundle->flip_addrs[planes_count].address.grph.addr.low_part); + } + +- full->surface_updates[planes_count].surface = dc_plane; ++ bundle->surface_updates[planes_count].surface = dc_plane; + if (new_pcrtc_state->color_mgmt_changed) { +- full->surface_updates[planes_count].gamma = dc_plane->gamma_correction; +- full->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func; ++ bundle->surface_updates[planes_count].gamma = dc_plane->gamma_correction; ++ bundle->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func; + } + + +- full->scaling_infos[planes_count].scaling_quality = dc_plane->scaling_quality; +- full->scaling_infos[planes_count].src_rect = dc_plane->src_rect; +- full->scaling_infos[planes_count].dst_rect = dc_plane->dst_rect; +- full->scaling_infos[planes_count].clip_rect = dc_plane->clip_rect; +- full->surface_updates[planes_count].scaling_info = &full->scaling_infos[planes_count]; ++ bundle->scaling_infos[planes_count].scaling_quality = dc_plane->scaling_quality; ++ bundle->scaling_infos[planes_count].src_rect = dc_plane->src_rect; ++ bundle->scaling_infos[planes_count].dst_rect = dc_plane->dst_rect; ++ bundle->scaling_infos[planes_count].clip_rect = dc_plane->clip_rect; ++ bundle->surface_updates[planes_count].scaling_info = &bundle->scaling_infos[planes_count]; + + +- full->plane_infos[planes_count].color_space = dc_plane->color_space; +- full->plane_infos[planes_count].format = dc_plane->format; +- full->plane_infos[planes_count].plane_size = dc_plane->plane_size; +- full->plane_infos[planes_count].rotation = dc_plane->rotation; +- full->plane_infos[planes_count].horizontal_mirror = dc_plane->horizontal_mirror; +- full->plane_infos[planes_count].stereo_format = dc_plane->stereo_format; +- full->plane_infos[planes_count].tiling_info = dc_plane->tiling_info; +- full->plane_infos[planes_count].visible = dc_plane->visible; +- full->plane_infos[planes_count].per_pixel_alpha = dc_plane->per_pixel_alpha; +- full->plane_infos[planes_count].dcc = dc_plane->dcc; +- full->surface_updates[planes_count].plane_info = &full->plane_infos[planes_count]; ++ bundle->plane_infos[planes_count].color_space = dc_plane->color_space; ++ bundle->plane_infos[planes_count].format = dc_plane->format; ++ bundle->plane_infos[planes_count].plane_size = dc_plane->plane_size; ++ bundle->plane_infos[planes_count].rotation = dc_plane->rotation; ++ bundle->plane_infos[planes_count].horizontal_mirror = dc_plane->horizontal_mirror; ++ bundle->plane_infos[planes_count].stereo_format = dc_plane->stereo_format; ++ bundle->plane_infos[planes_count].tiling_info = dc_plane->tiling_info; ++ bundle->plane_infos[planes_count].visible = dc_plane->visible; ++ bundle->plane_infos[planes_count].per_pixel_alpha = dc_plane->per_pixel_alpha; ++ bundle->plane_infos[planes_count].dcc = dc_plane->dcc; ++ bundle->surface_updates[planes_count].plane_info = &bundle->plane_infos[planes_count]; + + planes_count += 1; + + } + +- /* +- * TODO: For proper atomic behaviour, we should be calling into DC once with +- * all the changes. However, DC refuses to do pageflips and non-pageflip +- * changes in the same call. Change DC to respect atomic behaviour, +- * hopefully eliminating dc_*_update structs in their entirety. +- */ +- if (flip_count) { ++ if (pflip_present) { + target = (uint32_t)drm_crtc_vblank_count(pcrtc) + wait_for_vblank; + /* Prepare wait for target vblank early - before the fence-waits */ + target_vblank = target - (uint32_t)drm_crtc_vblank_count(pcrtc) + +@@ -4948,43 +4937,34 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, + if (acrtc_state->stream) { + + if (acrtc_state->freesync_timing_changed) +- flip->stream_update.adjust = ++ bundle->stream_update.adjust = + &acrtc_state->stream->adjust; + + if (acrtc_state->freesync_vrr_info_changed) +- flip->stream_update.vrr_infopacket = ++ bundle->stream_update.vrr_infopacket = + &acrtc_state->stream->vrr_infopacket; + } +- +- mutex_lock(&dm->dc_lock); +- dc_commit_updates_for_stream(dm->dc, +- flip->surface_updates, +- flip_count, +- acrtc_state->stream, +- &flip->stream_update, +- dc_state); +- mutex_unlock(&dm->dc_lock); + } + + if (planes_count) { + if (new_pcrtc_state->mode_changed) { +- full->stream_update.src = acrtc_state->stream->src; +- full->stream_update.dst = acrtc_state->stream->dst; ++ bundle->stream_update.src = acrtc_state->stream->src; ++ bundle->stream_update.dst = acrtc_state->stream->dst; + } + + if (new_pcrtc_state->color_mgmt_changed) +- full->stream_update.out_transfer_func = acrtc_state->stream->out_transfer_func; ++ bundle->stream_update.out_transfer_func = acrtc_state->stream->out_transfer_func; + + acrtc_state->stream->abm_level = acrtc_state->abm_level; + if (acrtc_state->abm_level != dm_old_crtc_state->abm_level) +- full->stream_update.abm_level = &acrtc_state->abm_level; ++ bundle->stream_update.abm_level = &acrtc_state->abm_level; + + mutex_lock(&dm->dc_lock); + dc_commit_updates_for_stream(dm->dc, +- full->surface_updates, ++ bundle->surface_updates, + planes_count, + acrtc_state->stream, +- &full->stream_update, ++ &bundle->stream_update, + dc_state); + mutex_unlock(&dm->dc_lock); + } +@@ -4994,8 +4974,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, + handle_cursor_update(plane, old_plane_state); + + cleanup: +- kfree(flip); +- kfree(full); ++ kfree(bundle); + } + + /* +-- +2.17.1 + |