]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/intel_fbc.c
Merge remote-tracking branch 'regmap/for-next'
[karo-tx-linux.git] / drivers / gpu / drm / i915 / intel_fbc.c
index 2c896f95d2c3a355e5b03498e35f557b04243b5b..3614a951736b395ed5e615beb881a0ec7ee51631 100644 (file)
@@ -43,7 +43,7 @@
 
 static inline bool fbc_supported(struct drm_i915_private *dev_priv)
 {
-       return dev_priv->fbc.activate != NULL;
+       return HAS_FBC(dev_priv);
 }
 
 static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
@@ -115,8 +115,6 @@ static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
        u32 fbc_ctl;
 
-       dev_priv->fbc.active = false;
-
        /* Disable compression */
        fbc_ctl = I915_READ(FBC_CONTROL);
        if ((fbc_ctl & FBC_CTL_EN) == 0)
@@ -139,8 +137,6 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
        int i;
        u32 fbc_ctl;
 
-       dev_priv->fbc.active = true;
-
        /* Note: fbc.threshold == 1 for i8xx */
        cfb_pitch = params->cfb_size / FBC_LL_SIZE;
        if (params->fb.stride < cfb_pitch)
@@ -187,8 +183,6 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
        struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
        u32 dpfc_ctl;
 
-       dev_priv->fbc.active = true;
-
        dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane) | DPFC_SR_EN;
        if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2)
                dpfc_ctl |= DPFC_CTL_LIMIT_2X;
@@ -206,8 +200,6 @@ static void g4x_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
        u32 dpfc_ctl;
 
-       dev_priv->fbc.active = false;
-
        /* Disable compression */
        dpfc_ctl = I915_READ(DPFC_CONTROL);
        if (dpfc_ctl & DPFC_CTL_EN) {
@@ -234,8 +226,6 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
        u32 dpfc_ctl;
        int threshold = dev_priv->fbc.threshold;
 
-       dev_priv->fbc.active = true;
-
        dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane);
        if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2)
                threshold++;
@@ -274,8 +264,6 @@ static void ilk_fbc_deactivate(struct drm_i915_private *dev_priv)
 {
        u32 dpfc_ctl;
 
-       dev_priv->fbc.active = false;
-
        /* Disable compression */
        dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
        if (dpfc_ctl & DPFC_CTL_EN) {
@@ -295,8 +283,6 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
        u32 dpfc_ctl;
        int threshold = dev_priv->fbc.threshold;
 
-       dev_priv->fbc.active = true;
-
        dpfc_ctl = 0;
        if (IS_IVYBRIDGE(dev_priv))
                dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.plane);
@@ -343,6 +329,46 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
        intel_fbc_recompress(dev_priv);
 }
 
+static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv)
+{
+       if (INTEL_INFO(dev_priv)->gen >= 5)
+               return ilk_fbc_is_active(dev_priv);
+       else if (IS_GM45(dev_priv))
+               return g4x_fbc_is_active(dev_priv);
+       else
+               return i8xx_fbc_is_active(dev_priv);
+}
+
+static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv)
+{
+       struct intel_fbc *fbc = &dev_priv->fbc;
+
+       fbc->active = true;
+
+       if (INTEL_INFO(dev_priv)->gen >= 7)
+               gen7_fbc_activate(dev_priv);
+       else if (INTEL_INFO(dev_priv)->gen >= 5)
+               ilk_fbc_activate(dev_priv);
+       else if (IS_GM45(dev_priv))
+               g4x_fbc_activate(dev_priv);
+       else
+               i8xx_fbc_activate(dev_priv);
+}
+
+static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv)
+{
+       struct intel_fbc *fbc = &dev_priv->fbc;
+
+       fbc->active = false;
+
+       if (INTEL_INFO(dev_priv)->gen >= 5)
+               ilk_fbc_deactivate(dev_priv);
+       else if (IS_GM45(dev_priv))
+               g4x_fbc_deactivate(dev_priv);
+       else
+               i8xx_fbc_deactivate(dev_priv);
+}
+
 /**
  * intel_fbc_is_active - Is FBC active?
  * @dev_priv: i915 device instance
@@ -405,7 +431,7 @@ retry:
                goto retry;
        }
 
-       fbc->activate(dev_priv);
+       intel_fbc_hw_activate(dev_priv);
 
        work->scheduled = false;
 
@@ -414,14 +440,6 @@ out:
        drm_crtc_vblank_put(&crtc->base);
 }
 
-static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv)
-{
-       struct intel_fbc *fbc = &dev_priv->fbc;
-
-       WARN_ON(!mutex_is_locked(&fbc->lock));
-       fbc->work.scheduled = false;
-}
-
 static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
@@ -436,10 +454,10 @@ static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
                return;
        }
 
-       /* It is useless to call intel_fbc_cancel_work() in this function since
-        * we're not releasing fbc.lock, so it won't have an opportunity to grab
-        * it to discover that it was cancelled. So we just update the expected
-        * jiffy count. */
+       /* It is useless to call intel_fbc_cancel_work() or cancel_work() in
+        * this function since we're not releasing fbc.lock, so it won't have an
+        * opportunity to grab it to discover that it was cancelled. So we just
+        * update the expected jiffy count. */
        work->scheduled = true;
        work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base);
        drm_crtc_vblank_put(&crtc->base);
@@ -453,23 +471,13 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
 
        WARN_ON(!mutex_is_locked(&fbc->lock));
 
-       intel_fbc_cancel_work(dev_priv);
+       /* Calling cancel_work() here won't help due to the fact that the work
+        * function grabs fbc->lock. Just set scheduled to false so the work
+        * function can know it was cancelled. */
+       fbc->work.scheduled = false;
 
        if (fbc->active)
-               fbc->deactivate(dev_priv);
-}
-
-static bool crtc_can_fbc(struct intel_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-
-       if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A)
-               return false;
-
-       if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A)
-               return false;
-
-       return true;
+               intel_fbc_hw_deactivate(dev_priv);
 }
 
 static bool multiple_pipes_ok(struct intel_crtc *crtc)
@@ -731,7 +739,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc)
 
        /* FIXME: We lack the proper locking here, so only run this on the
         * platforms that need. */
-       if (dev_priv->fbc.activate == ilk_fbc_activate)
+       if (INTEL_INFO(dev_priv)->gen >= 5 && INTEL_INFO(dev_priv)->gen < 7)
                cache->fb.ilk_ggtt_offset = i915_gem_obj_ggtt_offset(obj);
        cache->fb.pixel_format = fb->pixel_format;
        cache->fb.stride = fb->pitches[0];
@@ -831,11 +839,16 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc)
                return false;
        }
 
-       if (!crtc_can_fbc(crtc)) {
+       if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) {
                fbc->no_fbc_reason = "no enabled pipes can have FBC";
                return false;
        }
 
+       if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) {
+               fbc->no_fbc_reason = "no enabled planes can have FBC";
+               return false;
+       }
+
        return true;
 }
 
@@ -1236,30 +1249,13 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
                        break;
        }
 
-       if (INTEL_INFO(dev_priv)->gen >= 7) {
-               fbc->is_active = ilk_fbc_is_active;
-               fbc->activate = gen7_fbc_activate;
-               fbc->deactivate = ilk_fbc_deactivate;
-       } else if (INTEL_INFO(dev_priv)->gen >= 5) {
-               fbc->is_active = ilk_fbc_is_active;
-               fbc->activate = ilk_fbc_activate;
-               fbc->deactivate = ilk_fbc_deactivate;
-       } else if (IS_GM45(dev_priv)) {
-               fbc->is_active = g4x_fbc_is_active;
-               fbc->activate = g4x_fbc_activate;
-               fbc->deactivate = g4x_fbc_deactivate;
-       } else {
-               fbc->is_active = i8xx_fbc_is_active;
-               fbc->activate = i8xx_fbc_activate;
-               fbc->deactivate = i8xx_fbc_deactivate;
-
-               /* This value was pulled out of someone's hat */
+       /* This value was pulled out of someone's hat */
+       if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_GM45(dev_priv))
                I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
-       }
 
        /* We still don't have any sort of hardware state readout for FBC, so
         * deactivate it in case the BIOS activated it to make sure software
         * matches the hardware state. */
-       if (fbc->is_active(dev_priv))
-               fbc->deactivate(dev_priv);
+       if (intel_fbc_hw_is_active(dev_priv))
+               intel_fbc_hw_deactivate(dev_priv);
 }