aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/0146-drm-amd-display-Use-pflip-prepare-and-submit-parts-v.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/0146-drm-amd-display-Use-pflip-prepare-and-submit-parts-v.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/0146-drm-amd-display-Use-pflip-prepare-and-submit-parts-v.patch200
1 files changed, 200 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/0146-drm-amd-display-Use-pflip-prepare-and-submit-parts-v.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/0146-drm-amd-display-Use-pflip-prepare-and-submit-parts-v.patch
new file mode 100644
index 00000000..0f387b51
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/0146-drm-amd-display-Use-pflip-prepare-and-submit-parts-v.patch
@@ -0,0 +1,200 @@
+From 1459df7b197737022408e6348d800db2b6ce09cf Mon Sep 17 00:00:00 2001
+From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Date: Wed, 9 Nov 2016 05:41:51 -0500
+Subject: [PATCH 0146/4131] drm/amd/display: Use pflip prepare and submit parts
+ (v2)
+
+Use new functions so flip failures can be gracefully handled
+
+v2:
+Avoid -EINVAL returned from amdgpu_crtc_prepare_flip in some
+error cases, it is not allowed according to expected
+return values for atomic_commit hook.
+
+Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Acked-by: Harry Wentland <Harry.Wentland@amd.com>
+Reviewed-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 96 +++++++++++++++++++---
+ 1 file changed, 83 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+index 123dc94..a5e3a708 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+@@ -1646,6 +1646,7 @@ static void clear_unrelated_fields(struct drm_plane_state *state)
+ static bool page_flip_needed(
+ const struct drm_plane_state *new_state,
+ const struct drm_plane_state *old_state,
++ struct drm_pending_vblank_event *event,
+ bool commit_surface_required)
+ {
+ struct drm_plane_state old_state_tmp;
+@@ -1675,7 +1676,7 @@ static bool page_flip_needed(
+ old_state_tmp = *old_state;
+ new_state_tmp = *new_state;
+
+- if (!new_state->crtc->state->event)
++ if (!event)
+ return false;
+
+ amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb);
+@@ -2484,17 +2485,21 @@ int amdgpu_dm_atomic_commit(
+ struct amdgpu_device *adev = dev->dev_private;
+ struct amdgpu_display_manager *dm = &adev->dm;
+ struct drm_plane *plane;
++ struct drm_plane_state *new_plane_state;
+ struct drm_plane_state *old_plane_state;
+ uint32_t i;
+ int32_t ret = 0;
+ uint32_t commit_streams_count = 0;
+ uint32_t new_crtcs_count = 0;
++ uint32_t flip_crtcs_count = 0;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *old_crtc_state;
+-
+ const struct dc_stream *commit_streams[MAX_STREAMS];
+ struct amdgpu_crtc *new_crtcs[MAX_STREAMS];
+ const struct dc_stream *new_stream;
++ struct drm_crtc *flip_crtcs[MAX_STREAMS];
++ struct amdgpu_flip_work *work[MAX_STREAMS] = {0};
++ struct amdgpu_bo *new_abo[MAX_STREAMS] = {0};
+
+ /* In this step all new fb would be pinned */
+
+@@ -2510,6 +2515,61 @@ int amdgpu_dm_atomic_commit(
+ return ret;
+ }
+
++ /* Page flip if needed */
++ for_each_plane_in_state(state, plane, new_plane_state, i) {
++ struct drm_plane_state *old_plane_state = plane->state;
++ struct drm_crtc *crtc = new_plane_state->crtc;
++ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
++ struct drm_framebuffer *fb = new_plane_state->fb;
++ struct drm_crtc_state *crtc_state;
++
++ if (!fb || !crtc)
++ continue;
++
++ crtc_state = drm_atomic_get_crtc_state(state, crtc);
++
++ if (!crtc_state->planes_changed || !crtc_state->active)
++ continue;
++
++ if (page_flip_needed(
++ new_plane_state,
++ old_plane_state,
++ crtc_state->event,
++ false)) {
++ ret = amdgpu_crtc_prepare_flip(crtc,
++ fb,
++ crtc_state->event,
++ acrtc->flip_flags,
++ drm_crtc_vblank_count(crtc),
++ &work[flip_crtcs_count],
++ &new_abo[flip_crtcs_count]);
++
++ if (ret) {
++ /* According to atomic_commit hook API, EINVAL is not allowed */
++ if (unlikely(ret == -EINVAL))
++ ret = -ENOMEM;
++
++ DRM_ERROR("Atomic commit: Flip for crtc id %d: [%p], "
++ "failed, errno = %d\n",
++ acrtc->crtc_id,
++ acrtc,
++ ret);
++ /* cleanup all flip configurations which
++ * succeeded in this commit
++ */
++ for (i = 0; i < flip_crtcs_count; i++)
++ amdgpu_crtc_cleanup_flip_ctx(
++ work[i],
++ new_abo[i]);
++
++ return ret;
++ }
++
++ flip_crtcs[flip_crtcs_count] = crtc;
++ flip_crtcs_count++;
++ }
++ }
++
+ /*
+ * This is the point of no return - everything below never fails except
+ * when the hw goes bonghits. Which means we can commit the new state on
+@@ -2698,7 +2758,10 @@ int amdgpu_dm_atomic_commit(
+ * 1. This commit is not a page flip.
+ * 2. This commit is a page flip, and streams are created.
+ */
+- if (!page_flip_needed(plane_state, old_plane_state, true) ||
++ if (!page_flip_needed(
++ plane_state,
++ old_plane_state,
++ crtc->state->event, true) ||
+ action == DM_COMMIT_ACTION_DPMS_ON ||
+ action == DM_COMMIT_ACTION_SET) {
+ list_for_each_entry(connector,
+@@ -2754,7 +2817,8 @@ int amdgpu_dm_atomic_commit(
+
+ }
+
+- /* Page flip if needed */
++ /* Do actual flip */
++ flip_crtcs_count = 0;
+ for_each_plane_in_state(state, plane, old_plane_state, i) {
+ struct drm_plane_state *plane_state = plane->state;
+ struct drm_crtc *crtc = plane_state->crtc;
+@@ -2765,16 +2829,19 @@ int amdgpu_dm_atomic_commit(
+ !crtc->state->active)
+ continue;
+
+- if (page_flip_needed(plane_state, old_plane_state, false)) {
+- ret = amdgpu_crtc_page_flip_target(crtc,
+- fb,
+- crtc->state->event,
+- acrtc->flip_flags,
+- drm_crtc_vblank_count(crtc));
++ if (page_flip_needed(
++ plane_state,
++ old_plane_state,
++ crtc->state->event,
++ false)) {
++ amdgpu_crtc_submit_flip(
++ crtc,
++ fb,
++ work[flip_crtcs_count],
++ new_abo[i]);
++ flip_crtcs_count++;
+ /*clean up the flags for next usage*/
+ acrtc->flip_flags = 0;
+- if (ret)
+- return ret;
+ }
+ }
+
+@@ -3126,6 +3193,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ struct drm_connector *connector;
+ struct dm_connector_state *dm_state = NULL;
+ enum dm_commit_action action;
++ struct drm_crtc_state *crtc_state;
++
+
+ if (!fb || !crtc || crtc_set[i] != crtc ||
+ !crtc->state->planes_changed || !crtc->state->active)
+@@ -3137,8 +3206,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ * 1. This commit is not a page flip.
+ * 2. This commit is a page flip, and streams are created.
+ */
++ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (!page_flip_needed(plane_state, old_plane_state,
+- true) ||
++ crtc_state->event, true) ||
+ action == DM_COMMIT_ACTION_DPMS_ON ||
+ action == DM_COMMIT_ACTION_SET) {
+ struct dc_surface *surface;
+--
+2.7.4
+