drm/i915: Switch off FBC when disabling the primary plane when obscured
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 13 Jun 2012 16:36:55 +0000 (17:36 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 13 Jun 2012 18:10:00 +0000 (20:10 +0200)
As we switch on/off the primary plane if it is completely obscured by an
overlapping video sprite, we also nee to make sure that we update the
FBC configuration at the same time.

v2: Not all crtcs are intel_crtcs, as spotted by Daniel.
v3: Boot testing rules.

References: https://bugs.freedesktop.org/show_bug.cgi?id=50238
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sprite.c

index 1a1fdb088ddab8b73e69b03fbdeeef9cfeafcb2a..5290e9df327bf012a0fcf9fc87fb28a2d12b295f 100644 (file)
@@ -169,6 +169,7 @@ struct intel_crtc {
        u8 lut_r[256], lut_g[256], lut_b[256];
        int dpms_mode;
        bool active; /* is the crtc on? independent of the dpms mode */
+       bool primary_disabled; /* is the crtc obscured by a plane? */
        bool busy; /* is scanout buffer being updated frequently? */
        struct timer_list idle_timer;
        bool lowfreq_avail;
@@ -191,7 +192,6 @@ struct intel_plane {
        struct drm_plane base;
        enum pipe pipe;
        struct drm_i915_gem_object *obj;
-       bool primary_disabled;
        int max_downscale;
        u32 lut_r[1024], lut_g[1024], lut_b[1024];
        void (*update_plane)(struct drm_plane *plane,
index d0ce2a5b1d3f09ffa65340026388f5b5920e320a..b7de5ea62aa4c8f10138eec8aba07b9630c96869 100644 (file)
@@ -405,7 +405,9 @@ void intel_update_fbc(struct drm_device *dev)
         *   - going to an unsupported config (interlace, pixel multiply, etc.)
         */
        list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
-               if (tmp_crtc->enabled && tmp_crtc->fb) {
+               if (tmp_crtc->enabled &&
+                   !to_intel_crtc(tmp_crtc)->primary_disabled &&
+                   tmp_crtc->fb) {
                        if (crtc) {
                                DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
                                dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
index 2a20fb0781d7591018fdb7202d96ee7685e9cbba..9d7777bc15459abff49fc037c70f254db63a995b 100644 (file)
@@ -326,6 +326,12 @@ intel_enable_primary(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int reg = DSPCNTR(intel_crtc->plane);
 
+       if (!intel_crtc->primary_disabled)
+               return;
+
+       intel_crtc->primary_disabled = false;
+       intel_update_fbc(dev);
+
        I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
 }
 
@@ -337,7 +343,13 @@ intel_disable_primary(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int reg = DSPCNTR(intel_crtc->plane);
 
+       if (intel_crtc->primary_disabled)
+               return;
+
        I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
+
+       intel_crtc->primary_disabled = true;
+       intel_update_fbc(dev);
 }
 
 static int
@@ -485,18 +497,14 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
         * Be sure to re-enable the primary before the sprite is no longer
         * covering it fully.
         */
-       if (!disable_primary && intel_plane->primary_disabled) {
+       if (!disable_primary)
                intel_enable_primary(crtc);
-               intel_plane->primary_disabled = false;
-       }
 
        intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
                                  crtc_w, crtc_h, x, y, src_w, src_h);
 
-       if (disable_primary) {
+       if (disable_primary)
                intel_disable_primary(crtc);
-               intel_plane->primary_disabled = true;
-       }
 
        /* Unpin old obj after new one is active to avoid ugliness */
        if (old_obj) {
@@ -527,11 +535,8 @@ intel_disable_plane(struct drm_plane *plane)
        struct intel_plane *intel_plane = to_intel_plane(plane);
        int ret = 0;
 
-       if (intel_plane->primary_disabled) {
+       if (plane->crtc)
                intel_enable_primary(plane->crtc);
-               intel_plane->primary_disabled = false;
-       }
-
        intel_plane->disable_plane(plane);
 
        if (!intel_plane->obj)