These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / i915 / intel_frontbuffer.c
index a20cffb..ac85357 100644 (file)
 #include "intel_drv.h"
 #include "i915_drv.h"
 
-static void intel_increase_pllclock(struct drm_device *dev,
-                                   enum pipe pipe)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int dpll_reg = DPLL(pipe);
-       int dpll;
-
-       if (!HAS_GMCH_DISPLAY(dev))
-               return;
-
-       if (!dev_priv->lvds_downclock_avail)
-               return;
-
-       dpll = I915_READ(dpll_reg);
-       if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
-               DRM_DEBUG_DRIVER("upclocking LVDS\n");
-
-               assert_panel_unlocked(dev_priv, pipe);
-
-               dpll &= ~DISPLAY_RATE_SELECT_FPA1;
-               I915_WRITE(dpll_reg, dpll);
-               intel_wait_for_vblank(dev, pipe);
-
-               dpll = I915_READ(dpll_reg);
-               if (dpll & DISPLAY_RATE_SELECT_FPA1)
-                       DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
-       }
-}
-
-/**
- * intel_mark_fb_busy - mark given planes as busy
- * @dev: DRM device
- * @frontbuffer_bits: bits for the affected planes
- * @ring: optional ring for asynchronous commands
- *
- * This function gets called every time the screen contents change. It can be
- * used to keep e.g. the update rate at the nominal refresh rate with DRRS.
- */
-static void intel_mark_fb_busy(struct drm_device *dev,
-                              unsigned frontbuffer_bits,
-                              struct intel_engine_cs *ring)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       enum pipe pipe;
-
-       for_each_pipe(dev_priv, pipe) {
-               if (!(frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe)))
-                       continue;
-
-               intel_increase_pllclock(dev, pipe);
-       }
-}
-
 /**
  * intel_fb_obj_invalidate - invalidate frontbuffer object
  * @obj: GEM object to invalidate
- * @ring: set for asynchronous rendering
  * @origin: which operation caused the invalidation
  *
  * This function gets called every time rendering on the given object starts and
  * frontbuffer caching (fbc, low refresh rate for DRRS, panel self refresh) must
- * be invalidated. If @ring is non-NULL any subsequent invalidation will be delayed
+ * be invalidated. For ORIGIN_CS any subsequent invalidation will be delayed
  * until the rendering completes or a flip on this frontbuffer plane is
  * scheduled.
  */
 void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
-                            struct intel_engine_cs *ring,
                             enum fb_op_origin origin)
 {
        struct drm_device *dev = obj->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(dev);
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
        if (!obj->frontbuffer_bits)
                return;
 
-       if (ring) {
+       if (origin == ORIGIN_CS) {
                mutex_lock(&dev_priv->fb_tracking.lock);
                dev_priv->fb_tracking.busy_bits
                        |= obj->frontbuffer_bits;
@@ -151,8 +96,6 @@ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
                mutex_unlock(&dev_priv->fb_tracking.lock);
        }
 
-       intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring);
-
        intel_psr_invalidate(dev, obj->frontbuffer_bits);
        intel_edp_drrs_invalidate(dev, obj->frontbuffer_bits);
        intel_fbc_invalidate(dev_priv, obj->frontbuffer_bits, origin);
@@ -162,6 +105,7 @@ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
  * intel_frontbuffer_flush - flush frontbuffer
  * @dev: DRM device
  * @frontbuffer_bits: frontbuffer plane tracking bits
+ * @origin: which operation caused the flush
  *
  * This function gets called every time rendering on the given planes has
  * completed and frontbuffer caching can be started again. Flushes will get
@@ -169,37 +113,40 @@ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
  *
  * Can be called without any locks held.
  */
-void intel_frontbuffer_flush(struct drm_device *dev,
-                            unsigned frontbuffer_bits)
+static void intel_frontbuffer_flush(struct drm_device *dev,
+                                   unsigned frontbuffer_bits,
+                                   enum fb_op_origin origin)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(dev);
 
        /* Delay flushing when rings are still busy.*/
        mutex_lock(&dev_priv->fb_tracking.lock);
        frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits;
        mutex_unlock(&dev_priv->fb_tracking.lock);
 
-       intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
+       if (!frontbuffer_bits)
+               return;
 
        intel_edp_drrs_flush(dev, frontbuffer_bits);
-       intel_psr_flush(dev, frontbuffer_bits);
-       intel_fbc_flush(dev_priv, frontbuffer_bits);
+       intel_psr_flush(dev, frontbuffer_bits, origin);
+       intel_fbc_flush(dev_priv, frontbuffer_bits, origin);
 }
 
 /**
  * intel_fb_obj_flush - flush frontbuffer object
  * @obj: GEM object to flush
  * @retire: set when retiring asynchronous rendering
+ * @origin: which operation caused the flush
  *
  * This function gets called every time rendering on the given object has
  * completed and frontbuffer caching can be started again. If @retire is true
  * then any delayed flushes will be unblocked.
  */
 void intel_fb_obj_flush(struct drm_i915_gem_object *obj,
-                       bool retire)
+                       bool retire, enum fb_op_origin origin)
 {
        struct drm_device *dev = obj->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(dev);
        unsigned frontbuffer_bits;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -218,7 +165,7 @@ void intel_fb_obj_flush(struct drm_i915_gem_object *obj,
                mutex_unlock(&dev_priv->fb_tracking.lock);
        }
 
-       intel_frontbuffer_flush(dev, frontbuffer_bits);
+       intel_frontbuffer_flush(dev, frontbuffer_bits, origin);
 }
 
 /**
@@ -236,13 +183,15 @@ void intel_fb_obj_flush(struct drm_i915_gem_object *obj,
 void intel_frontbuffer_flip_prepare(struct drm_device *dev,
                                    unsigned frontbuffer_bits)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(dev);
 
        mutex_lock(&dev_priv->fb_tracking.lock);
        dev_priv->fb_tracking.flip_bits |= frontbuffer_bits;
        /* Remove stale busy bits due to the old buffer. */
        dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
        mutex_unlock(&dev_priv->fb_tracking.lock);
+
+       intel_psr_single_frame_update(dev, frontbuffer_bits);
 }
 
 /**
@@ -258,7 +207,7 @@ void intel_frontbuffer_flip_prepare(struct drm_device *dev,
 void intel_frontbuffer_flip_complete(struct drm_device *dev,
                                     unsigned frontbuffer_bits)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(dev);
 
        mutex_lock(&dev_priv->fb_tracking.lock);
        /* Mask any cancelled flips. */
@@ -266,5 +215,29 @@ void intel_frontbuffer_flip_complete(struct drm_device *dev,
        dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits;
        mutex_unlock(&dev_priv->fb_tracking.lock);
 
-       intel_frontbuffer_flush(dev, frontbuffer_bits);
+       intel_frontbuffer_flush(dev, frontbuffer_bits, ORIGIN_FLIP);
+}
+
+/**
+ * intel_frontbuffer_flip - synchronous frontbuffer flip
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called after scheduling a flip on @obj. This is for
+ * synchronous plane updates which will happen on the next vblank and which will
+ * not get delayed by pending gpu rendering.
+ *
+ * Can be called without any locks held.
+ */
+void intel_frontbuffer_flip(struct drm_device *dev,
+                           unsigned frontbuffer_bits)
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+
+       mutex_lock(&dev_priv->fb_tracking.lock);
+       /* Remove stale busy bits due to the old buffer. */
+       dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
+       mutex_unlock(&dev_priv->fb_tracking.lock);
+
+       intel_frontbuffer_flush(dev, frontbuffer_bits, ORIGIN_FLIP);
 }