[PATCH] drm/i915: Don't clobber plane state on internal disables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We need to disable all sprite planes when disabling the CRTC.  We had
been using the top-level atomic 'disable' entrypoint to accomplish this,
which was wrong.  Not only can this lead to various locking issues, it
also modifies the actual plane state, making it impossible to restore
the plane properly later.  For example, a DPMS off followed by a DPMS on
will result in any sprite planes in use not being restored properly.

The proper solution here is to call directly into our 'commit plane'
hook with a copy of the plane's current state that has 'visible' set to
false.  Committing this dummy state will turn off the plane, but will
not touch the actual plane->state pointer, allowing us to properly
restore the plane state later.

Signed-off-by: Matt Roper <matthew.d.roper@xxxxxxxxx>
---
This was a pretty big problem so I suspect this is probably tied to some of our
existing bugzilla's but I'm not sure exactly which ones.  It seems that we lack
an i-g-t test for plane status across DPMS, so I'll send along a new i-g-t test
for that shortly.

 drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 92cb2ff..6277701 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4201,6 +4201,24 @@ static void intel_enable_sprite_planes(struct drm_crtc *crtc)
 	}
 }
 
+/*
+ * Disable a plane internally without actually modifying the plane's state.
+ * This will allow us to easily restore the plane later by just reprogramming
+ * its state.
+ */
+static void disable_plane_internal(struct drm_plane *plane)
+{
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct drm_plane_state *state =
+		plane->funcs->atomic_duplicate_state(plane);
+	struct intel_plane_state *intel_state = to_intel_plane_state(state);
+
+	intel_state->visible = false;
+	intel_plane->commit_plane(plane, intel_state);
+
+	intel_plane_destroy_state(plane, state);
+}
+
 static void intel_disable_sprite_planes(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -4210,8 +4228,8 @@ static void intel_disable_sprite_planes(struct drm_crtc *crtc)
 
 	drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
 		intel_plane = to_intel_plane(plane);
-		if (intel_plane->pipe == pipe)
-			plane->funcs->disable_plane(plane);
+		if (plane->fb && intel_plane->pipe == pipe)
+			disable_plane_internal(plane);
 	}
 }
 
-- 
1.8.5.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx





[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux