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));
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;
}
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;
/**
* __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;
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;
*/
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)) {
/*
* 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);
}
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);
}
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);