[PATCH 3/3] drm/atomic: refuse changing CRTC for planes while active
Daniel Vetter
daniel.vetter at ffwll.ch
Wed Jul 29 05:01:10 PDT 2015
Very strictly speaking this is possible if you have special hw and
genlocked CRTCs. In general switching a plane between two active CRTC
just won't work so well and is probably not tested at all. Just forbid
it.
The exception is when both CRTC do a full modeset, then it should be
no problem at all to move the planes around (presuming a correct
implementation) so allow that case.
I've put this into the core since I really couldn't come up with a
case where we don't want to enforce that. But if that ever happens it
would be easy to move this check into helpers.
Cc: Thierry Reding <thierry.reding at gmail.com>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
---
drivers/gpu/drm/drm_atomic.c | 38 +++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_atomic_helper.c | 1 +
2 files changed, 39 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 434915448ea0..422183e7ee7d 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -663,6 +663,38 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
return 0;
}
+/* checks whether a plane has its CRTC switched while being in active use. */
+static bool
+active_plane_switching(struct drm_atomic_state *state,
+ struct drm_plane *plane,
+ struct drm_plane_state *plane_state)
+{
+ struct drm_crtc_state *crtc_state, *curr_crtc_state;
+
+ if (!plane->state->crtc || !plane_state->crtc)
+ return false;
+
+ if (plane->state->crtc == plane_state->crtc)
+ return false;
+
+ curr_crtc_state = plane->state->crtc->state;
+ if (!curr_crtc_state->active)
+ return false;
+
+ crtc_state = drm_atomic_get_existing_crtc_state(state,
+ plane_state->crtc);
+ if (!crtc_state->active)
+ return false;
+
+ /* plane switching CRTC and both CRTC are active. This is only ok if
+ * both CRTC do a full modeset. */
+ if (drm_atomic_crtc_needs_modeset(curr_crtc_state) &&
+ drm_atomic_crtc_needs_modeset(crtc_state))
+ return false;
+
+ return true;
+}
+
/**
* drm_atomic_plane_check - check plane state
* @plane: plane to check
@@ -734,6 +766,12 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
return -ENOSPC;
}
+ if (active_plane_switching(state->state, plane, state)) {
+ DRM_DEBUG_ATOMIC("[PLANE:%d] switching active CRTC without modeset\n",
+ plane->base.id);
+ return -EINVAL;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 6be0adb5a0e9..54c59ddc59a5 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -497,6 +497,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
plane->base.id);
return ret;
}
+
}
for_each_crtc_in_state(state, crtc, crtc_state, i) {
--
2.5.0
More information about the dri-devel
mailing list