summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_fbc.c
diff options
context:
space:
mode:
authorPaulo Zanoni2016-01-19 14:35:50 +0100
committerPaulo Zanoni2016-01-29 21:16:45 +0100
commitf51be2e0e3c54b7146152b39c1b5f569a005ab79 (patch)
tree14cb9e62b0a6407b304d88485eef9835775bebc6 /drivers/gpu/drm/i915/intel_fbc.c
parentdrm/i915: simplify struct drm_device access at intel_atomic_check() (diff)
downloadkernel-qcow2-linux-f51be2e0e3c54b7146152b39c1b5f569a005ab79.tar.gz
kernel-qcow2-linux-f51be2e0e3c54b7146152b39c1b5f569a005ab79.tar.xz
kernel-qcow2-linux-f51be2e0e3c54b7146152b39c1b5f569a005ab79.zip
drm/i915/fbc: choose the new FBC CRTC during atomic check
This opens the possibility of implementing nicer schemes to choose the CRTC, such as checking the amount of stolen memory available, or choosing the best pipe on platforms that don't die FBC to pipe or plane A. This code was written for another refactor that I ended up discarding, so I don't actually need it, but I figured this patch would be an improvement on its own so I kept it on the series. Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1453210558-7875-18-git-send-email-paulo.r.zanoni@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbc.c')
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c77
1 files changed, 71 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index c2ef400a9599..5bf7f844d827 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -826,7 +826,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
return true;
}
-static bool intel_fbc_can_enable(struct intel_crtc *crtc)
+static bool intel_fbc_can_choose(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
@@ -1015,11 +1015,76 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
}
/**
+ * 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 drm_atomic_state *state)
+{
+ struct intel_fbc *fbc = &dev_priv->fbc;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ struct drm_plane *plane;
+ struct drm_plane_state *plane_state;
+ bool fbc_crtc_present = false;
+ int i, j;
+
+ mutex_lock(&fbc->lock);
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (fbc->crtc == to_intel_crtc(crtc)) {
+ fbc_crtc_present = true;
+ break;
+ }
+ }
+ /* This atomic commit doesn't involve the CRTC currently tied to FBC. */
+ if (!fbc_crtc_present && fbc->crtc != NULL)
+ 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_plane_in_state(state, plane, plane_state, i) {
+ struct intel_plane_state *intel_plane_state =
+ to_intel_plane_state(plane_state);
+
+ if (!intel_plane_state->visible)
+ continue;
+
+ for_each_crtc_in_state(state, crtc, crtc_state, j) {
+ struct intel_crtc_state *intel_crtc_state =
+ to_intel_crtc_state(crtc_state);
+
+ if (plane_state->crtc != crtc)
+ continue;
+
+ if (!intel_fbc_can_choose(to_intel_crtc(crtc)))
+ break;
+
+ intel_crtc_state->enable_fbc = true;
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&fbc->lock);
+}
+
+/**
* intel_fbc_enable: tries to enable FBC on the CRTC
* @crtc: the CRTC
*
- * This function checks if it's possible to enable FBC on the following CRTC,
- * then enables it. Notice that it doesn't activate FBC.
+ * This function checks if the given CRTC was chosen for FBC, then enables it if
+ * possible. Notice that it doesn't activate FBC.
*/
void intel_fbc_enable(struct intel_crtc *crtc)
{
@@ -1036,12 +1101,12 @@ void intel_fbc_enable(struct intel_crtc *crtc)
goto out;
}
+ if (!crtc->config->enable_fbc)
+ goto out;
+
WARN_ON(fbc->active);
WARN_ON(fbc->crtc != NULL);
- if (!intel_fbc_can_enable(crtc))
- goto out;
-
intel_fbc_update_state_cache(crtc);
if (intel_fbc_alloc_cfb(crtc)) {
set_no_fbc_reason(dev_priv, "not enough stolen memory");