drm/i915: pass the crtc as an argument to intel_fbc_update()
authorPaulo Zanoni <paulo.r.zanoni@intel.com>
Tue, 13 Oct 2015 22:13:25 +0000 (19:13 -0300)
committerPaulo Zanoni <paulo.r.zanoni@intel.com>
Thu, 3 Dec 2015 13:32:13 +0000 (11:32 -0200)
There's no need to reevaluate the status of every single crtc when a
single crtc changes its state.

With this, we're cutting the case where due to a change in pipe B,
intel_fbc_update() is called, then intel_fbc_find_crtc() concludes FBC
should be enabled on pipe A, then it completely rechecks the state of
pipe A only to conclude FBC should remain enabled on pipe A. If any
change on pipe A triggers a need to recompute whether FBC is valid on
pipe A, then at some point someone is going to call
intel_fbc_update(PIPE_A).

The addition of intel_fbc_deactivate() is necessary so we keep track
of the previously selected CRTC when we do invalidate/flush. We're
also going to continue the enable/disable/activate/deactivate concept
in the next patches.

v2: Rebase.
v3: Rebase after changing the patch order.

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fbc.c

index edc034dc38b213908a359ae49e71c9098892d7ae..353fd6827c4a9093938a9a8310fad9597fa63173 100644 (file)
@@ -4792,7 +4792,6 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
 {
        struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
        struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (atomic->wait_vblank)
                intel_wait_for_vblank(dev, crtc->pipe);
@@ -4806,7 +4805,7 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
                intel_update_watermarks(&crtc->base);
 
        if (atomic->update_fbc)
-               intel_fbc_update(dev_priv);
+               intel_fbc_update(crtc);
 
        if (atomic->post_enable_primary)
                intel_post_enable_primary(&crtc->base);
index d82723b752cf035743a357da18b5d8ac8c9656d0..ae0a78b9a5c9b0ea13c2b73d555cd0617a3e66a9 100644 (file)
@@ -1323,7 +1323,7 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev)
 
 /* intel_fbc.c */
 bool intel_fbc_enabled(struct drm_i915_private *dev_priv);
-void intel_fbc_update(struct drm_i915_private *dev_priv);
+void intel_fbc_update(struct intel_crtc *crtc);
 void intel_fbc_init(struct drm_i915_private *dev_priv);
 void intel_fbc_disable(struct drm_i915_private *dev_priv);
 void intel_fbc_disable_crtc(struct intel_crtc *crtc);
index 70b55c0cf28e9215631f54548b5300bc917beb82..263d450b9bd7903542686ea93d035ac0c7d93cec 100644 (file)
@@ -429,7 +429,7 @@ static void intel_fbc_schedule_enable(struct intel_crtc *crtc)
        schedule_delayed_work(&work->work, msecs_to_jiffies(50));
 }
 
-static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
+static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
        WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
@@ -437,6 +437,11 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
 
        if (dev_priv->fbc.enabled)
                dev_priv->fbc.disable_fbc(dev_priv);
+}
+
+static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
+{
+       intel_fbc_deactivate(dev_priv);
        dev_priv->fbc.crtc = NULL;
 }
 
@@ -501,24 +506,6 @@ static bool crtc_is_valid(struct intel_crtc *crtc)
        return true;
 }
 
-static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
-{
-       struct drm_crtc *crtc = NULL, *tmp_crtc;
-       enum pipe pipe;
-
-       for_each_pipe(dev_priv, pipe) {
-               tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-
-               if (crtc_is_valid(to_intel_crtc(tmp_crtc)))
-                       crtc = tmp_crtc;
-       }
-
-       if (!crtc)
-               return NULL;
-
-       return crtc;
-}
-
 static bool multiple_pipes_ok(struct drm_i915_private *dev_priv)
 {
        enum pipe pipe;
@@ -804,21 +791,28 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
 
 /**
  * __intel_fbc_update - enable/disable FBC as needed, unlocked
- * @dev_priv: i915 device instance
+ * @crtc: the CRTC that triggered the update
  *
  * This function completely reevaluates the status of FBC, then enables,
  * disables or maintains it on the same state.
  */
-static void __intel_fbc_update(struct drm_i915_private *dev_priv)
+static void __intel_fbc_update(struct intel_crtc *crtc)
 {
-       struct drm_crtc *drm_crtc = NULL;
-       struct intel_crtc *crtc;
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
        struct drm_framebuffer *fb;
        struct drm_i915_gem_object *obj;
        const struct drm_display_mode *adjusted_mode;
 
        WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
 
+       if (!multiple_pipes_ok(dev_priv)) {
+               set_no_fbc_reason(dev_priv, "more than one pipe active");
+               goto out_disable;
+       }
+
+       if (dev_priv->fbc.crtc != NULL && dev_priv->fbc.crtc != crtc)
+               return;
+
        if (intel_vgpu_active(dev_priv->dev))
                i915.enable_fbc = 0;
 
@@ -832,18 +826,11 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
                goto out_disable;
        }
 
-       drm_crtc = intel_fbc_find_crtc(dev_priv);
-       if (!drm_crtc) {
+       if (!crtc_is_valid(crtc)) {
                set_no_fbc_reason(dev_priv, "no output");
                goto out_disable;
        }
 
-       if (!multiple_pipes_ok(dev_priv)) {
-               set_no_fbc_reason(dev_priv, "more than one pipe active");
-               goto out_disable;
-       }
-
-       crtc = to_intel_crtc(drm_crtc);
        fb = crtc->base.primary->fb;
        obj = intel_fb_obj(fb);
        adjusted_mode = &crtc->config->base.adjusted_mode;
@@ -909,7 +896,8 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
         */
        if (dev_priv->fbc.crtc == crtc &&
            dev_priv->fbc.fb_id == fb->base.id &&
-           dev_priv->fbc.y == crtc->base.y)
+           dev_priv->fbc.y == crtc->base.y &&
+           dev_priv->fbc.enabled)
                return;
 
        if (intel_fbc_enabled(dev_priv)) {
@@ -955,17 +943,19 @@ out_disable:
 
 /*
  * intel_fbc_update - enable/disable FBC as needed
- * @dev_priv: i915 device instance
+ * @crtc: the CRTC that triggered the update
  *
  * This function reevaluates the overall state and enables or disables FBC.
  */
-void intel_fbc_update(struct drm_i915_private *dev_priv)
+void intel_fbc_update(struct intel_crtc *crtc)
 {
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
        if (!fbc_supported(dev_priv))
                return;
 
        mutex_lock(&dev_priv->fbc.lock);
-       __intel_fbc_update(dev_priv);
+       __intel_fbc_update(crtc);
        mutex_unlock(&dev_priv->fbc.lock);
 }
 
@@ -991,7 +981,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
        dev_priv->fbc.busy_bits |= (fbc_bits & frontbuffer_bits);
 
        if (dev_priv->fbc.busy_bits)
-               __intel_fbc_disable(dev_priv);
+               intel_fbc_deactivate(dev_priv);
 
        mutex_unlock(&dev_priv->fbc.lock);
 }
@@ -1009,9 +999,9 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
 
        dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
 
-       if (!dev_priv->fbc.busy_bits) {
-               __intel_fbc_disable(dev_priv);
-               __intel_fbc_update(dev_priv);
+       if (!dev_priv->fbc.busy_bits && dev_priv->fbc.crtc) {
+               intel_fbc_deactivate(dev_priv);
+               __intel_fbc_update(dev_priv->fbc.crtc);
        }
 
        mutex_unlock(&dev_priv->fbc.lock);