summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_fbc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbc.c')
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 18e228bdf493..cf47352b7b8e 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -799,10 +799,16 @@ static bool pixel_format_is_valid(struct drm_framebuffer *fb)
}
}
-static bool pipe_size_is_valid(struct intel_crtc *crtc)
+/*
+ * For some reason, the hardware tracking starts looking at whatever we
+ * programmed as the display plane base address register. It does not look at
+ * the X and Y offset registers. That's why we look at the crtc->adjusted{x,y}
+ * variables instead of just looking at the pipe/plane size.
+ */
+static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
- unsigned int max_w, max_h;
+ unsigned int effective_w, effective_h, max_w, max_h;
if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
max_w = 4096;
@@ -815,8 +821,11 @@ static bool pipe_size_is_valid(struct intel_crtc *crtc)
max_h = 1536;
}
- return crtc->config->pipe_src_w <= max_w &&
- crtc->config->pipe_src_h <= max_h;
+ intel_fbc_get_plane_source_size(crtc, &effective_w, &effective_h);
+ effective_w += crtc->adjusted_x;
+ effective_h += crtc->adjusted_y;
+
+ return effective_w <= max_w && effective_h <= max_h;
}
/**
@@ -893,7 +902,7 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
goto out_disable;
}
- if (!pipe_size_is_valid(intel_crtc)) {
+ if (!intel_fbc_hw_tracking_covers_screen(intel_crtc)) {
set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE);
goto out_disable;
}