static bool intel_fbc_can_choose(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; bool enable_by_default = IS_BROADWELL(dev_priv); if (intel_vgpu_active(dev_priv->dev)) { fbc->no_fbc_reason = "VGPU is active"; return false; } if (i915.enable_fbc < 0 && !enable_by_default) { fbc->no_fbc_reason = "disabled per chip default"; return false; } if (!i915.enable_fbc) { fbc->no_fbc_reason = "disabled per module param"; return false; } if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) { fbc->no_fbc_reason = "no enabled pipes can have FBC"; return false; } if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) { fbc->no_fbc_reason = "no enabled planes can have FBC"; return false; } return true; }
/** * intel_fbc_choose_crtc - select a CRTC to enable FBC on * @dev_priv: i915 device instance * @state: the atomic state structure * * This function looks at the proposed state for CRTCs and planes, then chooses * which pipe is going to have FBC by setting intel_crtc_state->enable_fbc to * true. * * Later, intel_fbc_enable is going to look for state->enable_fbc and then maybe * enable FBC for the chosen CRTC. If it does, it will set dev_priv->fbc.crtc. */ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, struct intel_atomic_state *state) { struct intel_fbc *fbc = &dev_priv->fbc; struct intel_plane *plane; struct intel_plane_state *plane_state; bool crtc_chosen = false; int i; mutex_lock(&fbc->lock); /* Does this atomic commit involve the CRTC currently tied to FBC? */ if (fbc->crtc && !intel_atomic_get_new_crtc_state(state, fbc->crtc)) goto out; if (!intel_fbc_can_enable(dev_priv)) goto out; /* Simply choose the first CRTC that is compatible and has a visible * plane. We could go for fancier schemes such as checking the plane * size, but this would just affect the few platforms that don't tie FBC * to pipe or plane A. */ for_each_new_intel_plane_in_state(state, plane, plane_state, i) { struct intel_crtc_state *crtc_state; struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc); if (!plane_state->base.visible) continue; if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) continue; if (fbc_on_plane_a_only(dev_priv) && plane->i9xx_plane != PLANE_A) continue; crtc_state = intel_atomic_get_new_crtc_state(state, crtc); crtc_state->enable_fbc = true; crtc_chosen = true; break; } if (!crtc_chosen) fbc->no_fbc_reason = "no suitable CRTC for FBC"; out: mutex_unlock(&fbc->lock); }