diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbc.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_fbc.c | 19 |
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; } |