diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 25af60605e8f110771123763e1721202ac471b10..edd0999f61b4579dc4755278b7edf4bfbca7f5e9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4799,7 +4799,7 @@ static void intel_post_plane_update(struct intel_crtc *crtc) intel_update_watermarks(&crtc->base); if (atomic->update_fbc) - intel_fbc_update(crtc); + intel_fbc_post_update(crtc); if (atomic->post_enable_primary) intel_post_enable_primary(&crtc->base); @@ -4815,8 +4815,8 @@ static void intel_pre_plane_update(struct intel_crtc *crtc) struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->base.state); - if (atomic->disable_fbc) - intel_fbc_deactivate(crtc); + if (atomic->update_fbc) + intel_fbc_pre_update(crtc); if (crtc->atomic.disable_ips) hsw_disable_ips(crtc); @@ -10912,7 +10912,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) mutex_unlock(&dev->struct_mutex); intel_frontbuffer_flip_complete(dev, to_intel_plane(primary)->frontbuffer_bit); - intel_fbc_update(crtc); + intel_fbc_post_update(crtc); drm_framebuffer_unreference(work->old_fb); BUG_ON(atomic_read(&crtc->unpin_work_count) == 0); @@ -11712,7 +11712,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, to_intel_plane(primary)->frontbuffer_bit); mutex_unlock(&dev->struct_mutex); - intel_fbc_deactivate(intel_crtc); + intel_fbc_pre_update(intel_crtc); intel_frontbuffer_flip_prepare(dev, to_intel_plane(primary)->frontbuffer_bit); @@ -11901,7 +11901,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, case DRM_PLANE_TYPE_PRIMARY: intel_crtc->atomic.pre_disable_primary = turn_off; intel_crtc->atomic.post_enable_primary = turn_on; - intel_crtc->atomic.disable_fbc = true; intel_crtc->atomic.update_fbc = true; if (turn_off) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f620023ed1349507aaf3c9d59815a1537d539a89..b461d7307541d3994308d2bf6ef00b3fe40acc55 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -542,16 +542,17 @@ struct intel_mmio_flip { */ struct intel_crtc_atomic_commit { /* Sleepable operations to perform before commit */ - bool disable_fbc; bool disable_ips; bool pre_disable_primary; /* Sleepable operations to perform after commit */ unsigned fb_bits; bool wait_vblank; - bool update_fbc; bool post_enable_primary; unsigned update_sprite_watermarks; + + /* Sleepable operations to perform before and after commit */ + bool update_fbc; }; struct intel_crtc { @@ -1330,7 +1331,8 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev) /* intel_fbc.c */ bool intel_fbc_is_active(struct drm_i915_private *dev_priv); void intel_fbc_deactivate(struct intel_crtc *crtc); -void intel_fbc_update(struct intel_crtc *crtc); +void intel_fbc_pre_update(struct intel_crtc *crtc); +void intel_fbc_post_update(struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); void intel_fbc_enable(struct intel_crtc *crtc); void intel_fbc_disable(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 61523cd95ac1a8b01153df348308f10066dceb25..1c26d65cdd33aa661cb3e524e07dbebf95314a2d 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -510,6 +510,7 @@ static bool multiple_pipes_ok(struct drm_i915_private *dev_priv) if (INTEL_INFO(dev_priv)->gen > 4) return true; + /* FIXME: we don't have the appropriate state locks to do this here. */ for_each_pipe(dev_priv, pipe) { crtc = dev_priv->pipe_to_crtc_mapping[pipe]; @@ -732,12 +733,16 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; - struct intel_crtc_state *crtc_state = crtc->config; + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); struct intel_plane_state *plane_state = to_intel_plane_state(crtc->base.primary->state); struct drm_framebuffer *fb = plane_state->base.fb; struct drm_i915_gem_object *obj; + WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex)); + WARN_ON(!drm_modeset_is_locked(&crtc->base.primary->mutex)); + cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) cache->crtc.hsw_bdw_pixel_rate = @@ -896,12 +901,15 @@ static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1, return memcmp(params1, params2, sizeof(*params1)) == 0; } -static void intel_fbc_pre_update(struct intel_crtc *crtc) +void intel_fbc_pre_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; - WARN_ON(!mutex_is_locked(&fbc->lock)); + if (!fbc_supported(dev_priv)) + return; + + mutex_lock(&fbc->lock); if (!multiple_pipes_ok(dev_priv)) { set_no_fbc_reason(dev_priv, "more than one pipe active"); @@ -909,15 +917,17 @@ static void intel_fbc_pre_update(struct intel_crtc *crtc) } if (!fbc->enabled || fbc->crtc != crtc) - return; + goto unlock; intel_fbc_update_state_cache(crtc); deactivate: __intel_fbc_deactivate(dev_priv); +unlock: + mutex_unlock(&fbc->lock); } -static void intel_fbc_post_update(struct intel_crtc *crtc) +static void __intel_fbc_post_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; @@ -950,13 +960,7 @@ static void intel_fbc_post_update(struct intel_crtc *crtc) fbc->no_fbc_reason = "FBC enabled (active or scheduled)"; } -/* - * intel_fbc_update - activate/deactivate FBC as needed - * @crtc: the CRTC that triggered the update - * - * This function reevaluates the overall state and activates or deactivates FBC. - */ -void intel_fbc_update(struct intel_crtc *crtc) +void intel_fbc_post_update(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; @@ -965,8 +969,7 @@ void intel_fbc_update(struct intel_crtc *crtc) return; mutex_lock(&fbc->lock); - intel_fbc_pre_update(crtc); - intel_fbc_post_update(crtc); + __intel_fbc_post_update(crtc); mutex_unlock(&fbc->lock); } @@ -1020,7 +1023,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, if (fbc->active) intel_fbc_recompress(dev_priv); else - intel_fbc_post_update(fbc->crtc); + __intel_fbc_post_update(fbc->crtc); } mutex_unlock(&fbc->lock);