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; struct intel_fbc_reg_params old_params; WARN_ON(!mutex_is_locked(&fbc->lock)); if (!fbc->enabled || fbc->crtc != crtc) return; if (!intel_fbc_can_activate(crtc)) { WARN_ON(fbc->active); return; } old_params = fbc->params; intel_fbc_get_reg_params(crtc, &fbc->params); /* If the scanout has not changed, don't modify the FBC settings. * Note that we make the fundamental assumption that the fb->obj * cannot be unpinned (and have its GTT offset and fence revoked) * without first being decoupled from the scanout and FBC disabled. */ if (fbc->active && intel_fbc_reg_params_equal(&old_params, &fbc->params)) return; intel_fbc_deactivate(dev_priv); intel_fbc_schedule_activation(crtc); fbc->no_fbc_reason = "FBC enabled (active or scheduled)"; }
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; if (!fbc_supported(dev_priv)) return; mutex_lock(&fbc->lock); if (!multiple_pipes_ok(crtc)) { fbc->no_fbc_reason = "more than one pipe active"; goto deactivate; } if (!fbc->enabled || fbc->crtc != crtc) goto unlock; intel_fbc_update_state_cache(crtc); deactivate: intel_fbc_deactivate(dev_priv); unlock: mutex_unlock(&fbc->lock); }
void intel_fbc_pre_update(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; const char *reason = "update pending"; if (!fbc_supported(dev_priv)) return; mutex_lock(&fbc->lock); if (!multiple_pipes_ok(crtc, plane_state)) { reason = "more than one pipe active"; goto deactivate; } if (!fbc->enabled || fbc->crtc != crtc) goto unlock; intel_fbc_update_state_cache(crtc, crtc_state, plane_state); deactivate: intel_fbc_deactivate(dev_priv, reason); unlock: mutex_unlock(&fbc->lock); }
static void intel_fbc_underrun_work_fn(struct work_struct *work) { struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, fbc.underrun_work); struct intel_fbc *fbc = &dev_priv->fbc; mutex_lock(&fbc->lock); /* Maybe we were scheduled twice. */ if (fbc->underrun_detected || !fbc->enabled) goto out; DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n"); fbc->underrun_detected = true; intel_fbc_deactivate(dev_priv); out: mutex_unlock(&fbc->lock); }
void intel_fbc_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin) { struct intel_fbc *fbc = &dev_priv->fbc; if (!fbc_supported(dev_priv)) return; if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP) return; mutex_lock(&fbc->lock); fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits; if (fbc->enabled && fbc->busy_bits) intel_fbc_deactivate(dev_priv); mutex_unlock(&fbc->lock); }