X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=kernel%2Fdrivers%2Fgpu%2Fdrm%2Fi915%2Fintel_frontbuffer.c;fp=kernel%2Fdrivers%2Fgpu%2Fdrm%2Fi915%2Fintel_frontbuffer.c;h=ac85357010b4b652ec15811d9c7d4a3b52ad8ebd;hb=e09b41010ba33a20a87472ee821fa407a5b8da36;hp=a20cffb78c0f495055df8de87a0755e3a06cdb16;hpb=f93b97fd65072de626c074dbe099a1fff05ce060;p=kvmfornfv.git diff --git a/kernel/drivers/gpu/drm/i915/intel_frontbuffer.c b/kernel/drivers/gpu/drm/i915/intel_frontbuffer.c index a20cffb78..ac8535701 100644 --- a/kernel/drivers/gpu/drm/i915/intel_frontbuffer.c +++ b/kernel/drivers/gpu/drm/i915/intel_frontbuffer.c @@ -65,84 +65,29 @@ #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); }