xref: /dflybsd-src/sys/dev/drm/i915/intel_fbc.c (revision 87df8fc682f500d842f0b6cfa4b17a3d0fc13b35)
12c9916cdSFrançois Tigeot /*
22c9916cdSFrançois Tigeot  * Copyright © 2014 Intel Corporation
32c9916cdSFrançois Tigeot  *
42c9916cdSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
52c9916cdSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
62c9916cdSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
72c9916cdSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
82c9916cdSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
92c9916cdSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
102c9916cdSFrançois Tigeot  *
112c9916cdSFrançois Tigeot  * The above copyright notice and this permission notice (including the next
122c9916cdSFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
132c9916cdSFrançois Tigeot  * Software.
142c9916cdSFrançois Tigeot  *
152c9916cdSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
162c9916cdSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
172c9916cdSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
182c9916cdSFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
192c9916cdSFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
202c9916cdSFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
212c9916cdSFrançois Tigeot  * DEALINGS IN THE SOFTWARE.
222c9916cdSFrançois Tigeot  */
232c9916cdSFrançois Tigeot 
242c9916cdSFrançois Tigeot /**
252c9916cdSFrançois Tigeot  * DOC: Frame Buffer Compression (FBC)
262c9916cdSFrançois Tigeot  *
272c9916cdSFrançois Tigeot  * FBC tries to save memory bandwidth (and so power consumption) by
282c9916cdSFrançois Tigeot  * compressing the amount of memory used by the display. It is total
292c9916cdSFrançois Tigeot  * transparent to user space and completely handled in the kernel.
302c9916cdSFrançois Tigeot  *
312c9916cdSFrançois Tigeot  * The benefits of FBC are mostly visible with solid backgrounds and
322c9916cdSFrançois Tigeot  * variation-less patterns. It comes from keeping the memory footprint small
332c9916cdSFrançois Tigeot  * and having fewer memory pages opened and accessed for refreshing the display.
342c9916cdSFrançois Tigeot  *
352c9916cdSFrançois Tigeot  * i915 is responsible to reserve stolen memory for FBC and configure its
362c9916cdSFrançois Tigeot  * offset on proper registers. The hardware takes care of all
372c9916cdSFrançois Tigeot  * compress/decompress. However there are many known cases where we have to
382c9916cdSFrançois Tigeot  * forcibly disable it to allow proper screen updates.
392c9916cdSFrançois Tigeot  */
402c9916cdSFrançois Tigeot 
412c9916cdSFrançois Tigeot #include "intel_drv.h"
422c9916cdSFrançois Tigeot #include "i915_drv.h"
432c9916cdSFrançois Tigeot 
44352ff8bdSFrançois Tigeot static inline bool fbc_supported(struct drm_i915_private *dev_priv)
45352ff8bdSFrançois Tigeot {
46c0e85e96SFrançois Tigeot 	return HAS_FBC(dev_priv);
47aee94f86SFrançois Tigeot }
48aee94f86SFrançois Tigeot 
49aee94f86SFrançois Tigeot static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
50aee94f86SFrançois Tigeot {
51aee94f86SFrançois Tigeot 	return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8;
52aee94f86SFrançois Tigeot }
53aee94f86SFrançois Tigeot 
54aee94f86SFrançois Tigeot static inline bool fbc_on_plane_a_only(struct drm_i915_private *dev_priv)
55aee94f86SFrançois Tigeot {
56aee94f86SFrançois Tigeot 	return INTEL_INFO(dev_priv)->gen < 4;
57352ff8bdSFrançois Tigeot }
58352ff8bdSFrançois Tigeot 
59c0e85e96SFrançois Tigeot static inline bool no_fbc_on_multiple_pipes(struct drm_i915_private *dev_priv)
60c0e85e96SFrançois Tigeot {
61c0e85e96SFrançois Tigeot 	return INTEL_INFO(dev_priv)->gen <= 3;
62c0e85e96SFrançois Tigeot }
63c0e85e96SFrançois Tigeot 
64352ff8bdSFrançois Tigeot /*
65352ff8bdSFrançois Tigeot  * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the
66352ff8bdSFrançois Tigeot  * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's
67352ff8bdSFrançois Tigeot  * origin so the x and y offsets can actually fit the registers. As a
68352ff8bdSFrançois Tigeot  * consequence, the fence doesn't really start exactly at the display plane
69352ff8bdSFrançois Tigeot  * address we program because it starts at the real start of the buffer, so we
70352ff8bdSFrançois Tigeot  * have to take this into consideration here.
71352ff8bdSFrançois Tigeot  */
72352ff8bdSFrançois Tigeot static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)
73352ff8bdSFrançois Tigeot {
74352ff8bdSFrançois Tigeot 	return crtc->base.y - crtc->adjusted_y;
75352ff8bdSFrançois Tigeot }
76352ff8bdSFrançois Tigeot 
77aee94f86SFrançois Tigeot /*
78aee94f86SFrançois Tigeot  * For SKL+, the plane source size used by the hardware is based on the value we
79aee94f86SFrançois Tigeot  * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value
80aee94f86SFrançois Tigeot  * we wrote to PIPESRC.
81aee94f86SFrançois Tigeot  */
82c0e85e96SFrançois Tigeot static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache,
83aee94f86SFrançois Tigeot 					    int *width, int *height)
84aee94f86SFrançois Tigeot {
85aee94f86SFrançois Tigeot 	int w, h;
86aee94f86SFrançois Tigeot 
87c0e85e96SFrançois Tigeot 	if (intel_rotation_90_or_270(cache->plane.rotation)) {
88c0e85e96SFrançois Tigeot 		w = cache->plane.src_h;
89c0e85e96SFrançois Tigeot 		h = cache->plane.src_w;
90aee94f86SFrançois Tigeot 	} else {
91c0e85e96SFrançois Tigeot 		w = cache->plane.src_w;
92c0e85e96SFrançois Tigeot 		h = cache->plane.src_h;
93aee94f86SFrançois Tigeot 	}
94aee94f86SFrançois Tigeot 
95aee94f86SFrançois Tigeot 	if (width)
96aee94f86SFrançois Tigeot 		*width = w;
97aee94f86SFrançois Tigeot 	if (height)
98aee94f86SFrançois Tigeot 		*height = h;
99aee94f86SFrançois Tigeot }
100aee94f86SFrançois Tigeot 
101c0e85e96SFrançois Tigeot static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
102c0e85e96SFrançois Tigeot 					struct intel_fbc_state_cache *cache)
103aee94f86SFrançois Tigeot {
104aee94f86SFrançois Tigeot 	int lines;
105aee94f86SFrançois Tigeot 
106c0e85e96SFrançois Tigeot 	intel_fbc_get_plane_source_size(cache, NULL, &lines);
107bf017597SFrançois Tigeot 	if (INTEL_GEN(dev_priv) == 7)
108aee94f86SFrançois Tigeot 		lines = min(lines, 2048);
109bf017597SFrançois Tigeot 	else if (INTEL_GEN(dev_priv) >= 8)
110bf017597SFrançois Tigeot 		lines = min(lines, 2560);
111aee94f86SFrançois Tigeot 
112aee94f86SFrançois Tigeot 	/* Hardware needs the full buffer stride, not just the active area. */
113c0e85e96SFrançois Tigeot 	return lines * cache->fb.stride;
114aee94f86SFrançois Tigeot }
115aee94f86SFrançois Tigeot 
116aee94f86SFrançois Tigeot static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv)
1172c9916cdSFrançois Tigeot {
1182c9916cdSFrançois Tigeot 	u32 fbc_ctl;
1192c9916cdSFrançois Tigeot 
1202c9916cdSFrançois Tigeot 	/* Disable compression */
1212c9916cdSFrançois Tigeot 	fbc_ctl = I915_READ(FBC_CONTROL);
1222c9916cdSFrançois Tigeot 	if ((fbc_ctl & FBC_CTL_EN) == 0)
1232c9916cdSFrançois Tigeot 		return;
1242c9916cdSFrançois Tigeot 
1252c9916cdSFrançois Tigeot 	fbc_ctl &= ~FBC_CTL_EN;
1262c9916cdSFrançois Tigeot 	I915_WRITE(FBC_CONTROL, fbc_ctl);
1272c9916cdSFrançois Tigeot 
1282c9916cdSFrançois Tigeot 	/* Wait for compressing bit to clear */
1291487f786SFrançois Tigeot 	if (intel_wait_for_register(dev_priv,
1301487f786SFrançois Tigeot 				    FBC_STATUS, FBC_STAT_COMPRESSING, 0,
1311487f786SFrançois Tigeot 				    10)) {
1322c9916cdSFrançois Tigeot 		DRM_DEBUG_KMS("FBC idle timed out\n");
1332c9916cdSFrançois Tigeot 		return;
1342c9916cdSFrançois Tigeot 	}
1352c9916cdSFrançois Tigeot }
1362c9916cdSFrançois Tigeot 
137c0e85e96SFrançois Tigeot static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
1382c9916cdSFrançois Tigeot {
139c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
1402c9916cdSFrançois Tigeot 	int cfb_pitch;
1412c9916cdSFrançois Tigeot 	int i;
1422c9916cdSFrançois Tigeot 	u32 fbc_ctl;
1432c9916cdSFrançois Tigeot 
144477eb7f9SFrançois Tigeot 	/* Note: fbc.threshold == 1 for i8xx */
145c0e85e96SFrançois Tigeot 	cfb_pitch = params->cfb_size / FBC_LL_SIZE;
146c0e85e96SFrançois Tigeot 	if (params->fb.stride < cfb_pitch)
147c0e85e96SFrançois Tigeot 		cfb_pitch = params->fb.stride;
1482c9916cdSFrançois Tigeot 
1492c9916cdSFrançois Tigeot 	/* FBC_CTL wants 32B or 64B units */
150a05eeebfSFrançois Tigeot 	if (IS_GEN2(dev_priv))
1512c9916cdSFrançois Tigeot 		cfb_pitch = (cfb_pitch / 32) - 1;
1522c9916cdSFrançois Tigeot 	else
1532c9916cdSFrançois Tigeot 		cfb_pitch = (cfb_pitch / 64) - 1;
1542c9916cdSFrançois Tigeot 
1552c9916cdSFrançois Tigeot 	/* Clear old tags */
1562c9916cdSFrançois Tigeot 	for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
157352ff8bdSFrançois Tigeot 		I915_WRITE(FBC_TAG(i), 0);
1582c9916cdSFrançois Tigeot 
159a05eeebfSFrançois Tigeot 	if (IS_GEN4(dev_priv)) {
1602c9916cdSFrançois Tigeot 		u32 fbc_ctl2;
1612c9916cdSFrançois Tigeot 
1622c9916cdSFrançois Tigeot 		/* Set it up... */
1632c9916cdSFrançois Tigeot 		fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
164c0e85e96SFrançois Tigeot 		fbc_ctl2 |= FBC_CTL_PLANE(params->crtc.plane);
1652c9916cdSFrançois Tigeot 		I915_WRITE(FBC_CONTROL2, fbc_ctl2);
166c0e85e96SFrançois Tigeot 		I915_WRITE(FBC_FENCE_OFF, params->crtc.fence_y_offset);
1672c9916cdSFrançois Tigeot 	}
1682c9916cdSFrançois Tigeot 
1692c9916cdSFrançois Tigeot 	/* enable it... */
1702c9916cdSFrançois Tigeot 	fbc_ctl = I915_READ(FBC_CONTROL);
1712c9916cdSFrançois Tigeot 	fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT;
1722c9916cdSFrançois Tigeot 	fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
173a05eeebfSFrançois Tigeot 	if (IS_I945GM(dev_priv))
1742c9916cdSFrançois Tigeot 		fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
1752c9916cdSFrançois Tigeot 	fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
176c0e85e96SFrançois Tigeot 	fbc_ctl |= params->fb.fence_reg;
1772c9916cdSFrançois Tigeot 	I915_WRITE(FBC_CONTROL, fbc_ctl);
1782c9916cdSFrançois Tigeot }
1792c9916cdSFrançois Tigeot 
180aee94f86SFrançois Tigeot static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv)
1812c9916cdSFrançois Tigeot {
1822c9916cdSFrançois Tigeot 	return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
1832c9916cdSFrançois Tigeot }
1842c9916cdSFrançois Tigeot 
185c0e85e96SFrançois Tigeot static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
1862c9916cdSFrançois Tigeot {
187c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
1882c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
1892c9916cdSFrançois Tigeot 
190c0e85e96SFrançois Tigeot 	dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane) | DPFC_SR_EN;
191c0e85e96SFrançois Tigeot 	if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2)
1922c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
1932c9916cdSFrançois Tigeot 	else
1942c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
195c0e85e96SFrançois Tigeot 	dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg;
1962c9916cdSFrançois Tigeot 
197c0e85e96SFrançois Tigeot 	I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
1982c9916cdSFrançois Tigeot 
1992c9916cdSFrançois Tigeot 	/* enable it... */
2002c9916cdSFrançois Tigeot 	I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
2012c9916cdSFrançois Tigeot }
2022c9916cdSFrançois Tigeot 
203aee94f86SFrançois Tigeot static void g4x_fbc_deactivate(struct drm_i915_private *dev_priv)
2042c9916cdSFrançois Tigeot {
2052c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
2062c9916cdSFrançois Tigeot 
2072c9916cdSFrançois Tigeot 	/* Disable compression */
2082c9916cdSFrançois Tigeot 	dpfc_ctl = I915_READ(DPFC_CONTROL);
2092c9916cdSFrançois Tigeot 	if (dpfc_ctl & DPFC_CTL_EN) {
2102c9916cdSFrançois Tigeot 		dpfc_ctl &= ~DPFC_CTL_EN;
2112c9916cdSFrançois Tigeot 		I915_WRITE(DPFC_CONTROL, dpfc_ctl);
2122c9916cdSFrançois Tigeot 	}
2132c9916cdSFrançois Tigeot }
2142c9916cdSFrançois Tigeot 
215aee94f86SFrançois Tigeot static bool g4x_fbc_is_active(struct drm_i915_private *dev_priv)
2162c9916cdSFrançois Tigeot {
2172c9916cdSFrançois Tigeot 	return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
2182c9916cdSFrançois Tigeot }
2192c9916cdSFrançois Tigeot 
220aee94f86SFrançois Tigeot /* This function forces a CFB recompression through the nuke operation. */
221aee94f86SFrançois Tigeot static void intel_fbc_recompress(struct drm_i915_private *dev_priv)
2222c9916cdSFrançois Tigeot {
223477eb7f9SFrançois Tigeot 	I915_WRITE(MSG_FBC_REND_STATE, FBC_REND_NUKE);
224477eb7f9SFrançois Tigeot 	POSTING_READ(MSG_FBC_REND_STATE);
2252c9916cdSFrançois Tigeot }
2262c9916cdSFrançois Tigeot 
227c0e85e96SFrançois Tigeot static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
2282c9916cdSFrançois Tigeot {
229c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
2302c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
231a05eeebfSFrançois Tigeot 	int threshold = dev_priv->fbc.threshold;
2322c9916cdSFrançois Tigeot 
233c0e85e96SFrançois Tigeot 	dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane);
234c0e85e96SFrançois Tigeot 	if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2)
235a05eeebfSFrançois Tigeot 		threshold++;
2362c9916cdSFrançois Tigeot 
237a05eeebfSFrançois Tigeot 	switch (threshold) {
2382c9916cdSFrançois Tigeot 	case 4:
2392c9916cdSFrançois Tigeot 	case 3:
2402c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_4X;
2412c9916cdSFrançois Tigeot 		break;
2422c9916cdSFrançois Tigeot 	case 2:
2432c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
2442c9916cdSFrançois Tigeot 		break;
2452c9916cdSFrançois Tigeot 	case 1:
2462c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
2472c9916cdSFrançois Tigeot 		break;
2482c9916cdSFrançois Tigeot 	}
2492c9916cdSFrançois Tigeot 	dpfc_ctl |= DPFC_CTL_FENCE_EN;
250a05eeebfSFrançois Tigeot 	if (IS_GEN5(dev_priv))
251c0e85e96SFrançois Tigeot 		dpfc_ctl |= params->fb.fence_reg;
2522c9916cdSFrançois Tigeot 
253c0e85e96SFrançois Tigeot 	I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
254c0e85e96SFrançois Tigeot 	I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID);
2552c9916cdSFrançois Tigeot 	/* enable it... */
2562c9916cdSFrançois Tigeot 	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
2572c9916cdSFrançois Tigeot 
258a05eeebfSFrançois Tigeot 	if (IS_GEN6(dev_priv)) {
2592c9916cdSFrançois Tigeot 		I915_WRITE(SNB_DPFC_CTL_SA,
260c0e85e96SFrançois Tigeot 			   SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
261c0e85e96SFrançois Tigeot 		I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
2622c9916cdSFrançois Tigeot 	}
2632c9916cdSFrançois Tigeot 
264aee94f86SFrançois Tigeot 	intel_fbc_recompress(dev_priv);
2652c9916cdSFrançois Tigeot }
2662c9916cdSFrançois Tigeot 
267aee94f86SFrançois Tigeot static void ilk_fbc_deactivate(struct drm_i915_private *dev_priv)
2682c9916cdSFrançois Tigeot {
2692c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
2702c9916cdSFrançois Tigeot 
2712c9916cdSFrançois Tigeot 	/* Disable compression */
2722c9916cdSFrançois Tigeot 	dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
2732c9916cdSFrançois Tigeot 	if (dpfc_ctl & DPFC_CTL_EN) {
2742c9916cdSFrançois Tigeot 		dpfc_ctl &= ~DPFC_CTL_EN;
2752c9916cdSFrançois Tigeot 		I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
2762c9916cdSFrançois Tigeot 	}
2772c9916cdSFrançois Tigeot }
2782c9916cdSFrançois Tigeot 
279aee94f86SFrançois Tigeot static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv)
2802c9916cdSFrançois Tigeot {
2812c9916cdSFrançois Tigeot 	return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
2822c9916cdSFrançois Tigeot }
2832c9916cdSFrançois Tigeot 
284c0e85e96SFrançois Tigeot static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
2852c9916cdSFrançois Tigeot {
286c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
2872c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
288a05eeebfSFrançois Tigeot 	int threshold = dev_priv->fbc.threshold;
2892c9916cdSFrançois Tigeot 
290a05eeebfSFrançois Tigeot 	dpfc_ctl = 0;
291a05eeebfSFrançois Tigeot 	if (IS_IVYBRIDGE(dev_priv))
292c0e85e96SFrançois Tigeot 		dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.plane);
2932c9916cdSFrançois Tigeot 
294c0e85e96SFrançois Tigeot 	if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2)
295a05eeebfSFrançois Tigeot 		threshold++;
296a05eeebfSFrançois Tigeot 
297a05eeebfSFrançois Tigeot 	switch (threshold) {
2982c9916cdSFrançois Tigeot 	case 4:
2992c9916cdSFrançois Tigeot 	case 3:
3002c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_4X;
3012c9916cdSFrançois Tigeot 		break;
3022c9916cdSFrançois Tigeot 	case 2:
3032c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
3042c9916cdSFrançois Tigeot 		break;
3052c9916cdSFrançois Tigeot 	case 1:
3062c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
3072c9916cdSFrançois Tigeot 		break;
3082c9916cdSFrançois Tigeot 	}
3092c9916cdSFrançois Tigeot 
3102c9916cdSFrançois Tigeot 	dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
3112c9916cdSFrançois Tigeot 
3122c9916cdSFrançois Tigeot 	if (dev_priv->fbc.false_color)
3132c9916cdSFrançois Tigeot 		dpfc_ctl |= FBC_CTL_FALSE_COLOR;
3142c9916cdSFrançois Tigeot 
315a05eeebfSFrançois Tigeot 	if (IS_IVYBRIDGE(dev_priv)) {
3162c9916cdSFrançois Tigeot 		/* WaFbcAsynchFlipDisableFbcQueue:ivb */
3172c9916cdSFrançois Tigeot 		I915_WRITE(ILK_DISPLAY_CHICKEN1,
3182c9916cdSFrançois Tigeot 			   I915_READ(ILK_DISPLAY_CHICKEN1) |
3192c9916cdSFrançois Tigeot 			   ILK_FBCQ_DIS);
320352ff8bdSFrançois Tigeot 	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
3212c9916cdSFrançois Tigeot 		/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
322c0e85e96SFrançois Tigeot 		I915_WRITE(CHICKEN_PIPESL_1(params->crtc.pipe),
323c0e85e96SFrançois Tigeot 			   I915_READ(CHICKEN_PIPESL_1(params->crtc.pipe)) |
3242c9916cdSFrançois Tigeot 			   HSW_FBCQ_DIS);
3252c9916cdSFrançois Tigeot 	}
3262c9916cdSFrançois Tigeot 
327352ff8bdSFrançois Tigeot 	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
328352ff8bdSFrançois Tigeot 
3292c9916cdSFrançois Tigeot 	I915_WRITE(SNB_DPFC_CTL_SA,
330c0e85e96SFrançois Tigeot 		   SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
331c0e85e96SFrançois Tigeot 	I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
3322c9916cdSFrançois Tigeot 
333aee94f86SFrançois Tigeot 	intel_fbc_recompress(dev_priv);
3342c9916cdSFrançois Tigeot }
3352c9916cdSFrançois Tigeot 
336c0e85e96SFrançois Tigeot static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv)
337c0e85e96SFrançois Tigeot {
338c0e85e96SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 5)
339c0e85e96SFrançois Tigeot 		return ilk_fbc_is_active(dev_priv);
340c0e85e96SFrançois Tigeot 	else if (IS_GM45(dev_priv))
341c0e85e96SFrançois Tigeot 		return g4x_fbc_is_active(dev_priv);
342c0e85e96SFrançois Tigeot 	else
343c0e85e96SFrançois Tigeot 		return i8xx_fbc_is_active(dev_priv);
344c0e85e96SFrançois Tigeot }
345c0e85e96SFrançois Tigeot 
346c0e85e96SFrançois Tigeot static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv)
347c0e85e96SFrançois Tigeot {
348c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
349c0e85e96SFrançois Tigeot 
350c0e85e96SFrançois Tigeot 	fbc->active = true;
351c0e85e96SFrançois Tigeot 
352c0e85e96SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 7)
353c0e85e96SFrançois Tigeot 		gen7_fbc_activate(dev_priv);
354c0e85e96SFrançois Tigeot 	else if (INTEL_INFO(dev_priv)->gen >= 5)
355c0e85e96SFrançois Tigeot 		ilk_fbc_activate(dev_priv);
356c0e85e96SFrançois Tigeot 	else if (IS_GM45(dev_priv))
357c0e85e96SFrançois Tigeot 		g4x_fbc_activate(dev_priv);
358c0e85e96SFrançois Tigeot 	else
359c0e85e96SFrançois Tigeot 		i8xx_fbc_activate(dev_priv);
360c0e85e96SFrançois Tigeot }
361c0e85e96SFrançois Tigeot 
362c0e85e96SFrançois Tigeot static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv)
363c0e85e96SFrançois Tigeot {
364c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
365c0e85e96SFrançois Tigeot 
366c0e85e96SFrançois Tigeot 	fbc->active = false;
367c0e85e96SFrançois Tigeot 
368c0e85e96SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 5)
369c0e85e96SFrançois Tigeot 		ilk_fbc_deactivate(dev_priv);
370c0e85e96SFrançois Tigeot 	else if (IS_GM45(dev_priv))
371c0e85e96SFrançois Tigeot 		g4x_fbc_deactivate(dev_priv);
372c0e85e96SFrançois Tigeot 	else
373c0e85e96SFrançois Tigeot 		i8xx_fbc_deactivate(dev_priv);
374c0e85e96SFrançois Tigeot }
375c0e85e96SFrançois Tigeot 
3762c9916cdSFrançois Tigeot /**
377aee94f86SFrançois Tigeot  * intel_fbc_is_active - Is FBC active?
378a05eeebfSFrançois Tigeot  * @dev_priv: i915 device instance
3792c9916cdSFrançois Tigeot  *
3802c9916cdSFrançois Tigeot  * This function is used to verify the current state of FBC.
3811487f786SFrançois Tigeot  *
3822c9916cdSFrançois Tigeot  * FIXME: This should be tracked in the plane config eventually
3832c9916cdSFrançois Tigeot  * instead of queried at runtime for most callers.
3842c9916cdSFrançois Tigeot  */
385aee94f86SFrançois Tigeot bool intel_fbc_is_active(struct drm_i915_private *dev_priv)
3862c9916cdSFrançois Tigeot {
387aee94f86SFrançois Tigeot 	return dev_priv->fbc.active;
3882c9916cdSFrançois Tigeot }
3892c9916cdSFrançois Tigeot 
3902c9916cdSFrançois Tigeot static void intel_fbc_work_fn(struct work_struct *__work)
3912c9916cdSFrançois Tigeot {
392aee94f86SFrançois Tigeot 	struct drm_i915_private *dev_priv =
393aee94f86SFrançois Tigeot 		container_of(__work, struct drm_i915_private, fbc.work.work);
394c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
395c0e85e96SFrançois Tigeot 	struct intel_fbc_work *work = &fbc->work;
396c0e85e96SFrançois Tigeot 	struct intel_crtc *crtc = fbc->crtc;
397303bf270SFrançois Tigeot 	struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[crtc->pipe];
398c0e85e96SFrançois Tigeot 
399c0e85e96SFrançois Tigeot 	if (drm_crtc_vblank_get(&crtc->base)) {
400c0e85e96SFrançois Tigeot 		DRM_ERROR("vblank not available for FBC on pipe %c\n",
401c0e85e96SFrançois Tigeot 			  pipe_name(crtc->pipe));
402c0e85e96SFrançois Tigeot 
403c0e85e96SFrançois Tigeot 		mutex_lock(&fbc->lock);
404c0e85e96SFrançois Tigeot 		work->scheduled = false;
405c0e85e96SFrançois Tigeot 		mutex_unlock(&fbc->lock);
406c0e85e96SFrançois Tigeot 		return;
407c0e85e96SFrançois Tigeot 	}
4082c9916cdSFrançois Tigeot 
409aee94f86SFrançois Tigeot retry:
4102c9916cdSFrançois Tigeot 	/* Delay the actual enabling to let pageflipping cease and the
4112c9916cdSFrançois Tigeot 	 * display to settle before starting the compression. Note that
4122c9916cdSFrançois Tigeot 	 * this delay also serves a second purpose: it allows for a
4132c9916cdSFrançois Tigeot 	 * vblank to pass after disabling the FBC before we attempt
4142c9916cdSFrançois Tigeot 	 * to modify the control registers.
4152c9916cdSFrançois Tigeot 	 *
4162c9916cdSFrançois Tigeot 	 * WaFbcWaitForVBlankBeforeEnable:ilk,snb
417c0e85e96SFrançois Tigeot 	 *
418c0e85e96SFrançois Tigeot 	 * It is also worth mentioning that since work->scheduled_vblank can be
419c0e85e96SFrançois Tigeot 	 * updated multiple times by the other threads, hitting the timeout is
420c0e85e96SFrançois Tigeot 	 * not an error condition. We'll just end up hitting the "goto retry"
421c0e85e96SFrançois Tigeot 	 * case below.
4222c9916cdSFrançois Tigeot 	 */
423c0e85e96SFrançois Tigeot 	wait_event_timeout(vblank->queue,
424c0e85e96SFrançois Tigeot 		drm_crtc_vblank_count(&crtc->base) != work->scheduled_vblank,
425c0e85e96SFrançois Tigeot 		msecs_to_jiffies(50));
426aee94f86SFrançois Tigeot 
427c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
428aee94f86SFrançois Tigeot 
429aee94f86SFrançois Tigeot 	/* Were we cancelled? */
430aee94f86SFrançois Tigeot 	if (!work->scheduled)
431aee94f86SFrançois Tigeot 		goto out;
432aee94f86SFrançois Tigeot 
433aee94f86SFrançois Tigeot 	/* Were we delayed again while this function was sleeping? */
434c0e85e96SFrançois Tigeot 	if (drm_crtc_vblank_count(&crtc->base) == work->scheduled_vblank) {
435c0e85e96SFrançois Tigeot 		mutex_unlock(&fbc->lock);
436aee94f86SFrançois Tigeot 		goto retry;
4372c9916cdSFrançois Tigeot 	}
4382c9916cdSFrançois Tigeot 
439c0e85e96SFrançois Tigeot 	intel_fbc_hw_activate(dev_priv);
440aee94f86SFrançois Tigeot 
441aee94f86SFrançois Tigeot 	work->scheduled = false;
442aee94f86SFrançois Tigeot 
443aee94f86SFrançois Tigeot out:
444c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
445c0e85e96SFrançois Tigeot 	drm_crtc_vblank_put(&crtc->base);
446aee94f86SFrançois Tigeot }
447aee94f86SFrançois Tigeot 
448aee94f86SFrançois Tigeot static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
449aee94f86SFrançois Tigeot {
450303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
451c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
452c0e85e96SFrançois Tigeot 	struct intel_fbc_work *work = &fbc->work;
453aee94f86SFrançois Tigeot 
454c0e85e96SFrançois Tigeot 	WARN_ON(!mutex_is_locked(&fbc->lock));
455aee94f86SFrançois Tigeot 
456c0e85e96SFrançois Tigeot 	if (drm_crtc_vblank_get(&crtc->base)) {
457c0e85e96SFrançois Tigeot 		DRM_ERROR("vblank not available for FBC on pipe %c\n",
458c0e85e96SFrançois Tigeot 			  pipe_name(crtc->pipe));
459c0e85e96SFrançois Tigeot 		return;
460c0e85e96SFrançois Tigeot 	}
461c0e85e96SFrançois Tigeot 
462c0e85e96SFrançois Tigeot 	/* It is useless to call intel_fbc_cancel_work() or cancel_work() in
463c0e85e96SFrançois Tigeot 	 * this function since we're not releasing fbc.lock, so it won't have an
464c0e85e96SFrançois Tigeot 	 * opportunity to grab it to discover that it was cancelled. So we just
465c0e85e96SFrançois Tigeot 	 * update the expected jiffy count. */
466aee94f86SFrançois Tigeot 	work->scheduled = true;
467c0e85e96SFrançois Tigeot 	work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base);
468c0e85e96SFrançois Tigeot 	drm_crtc_vblank_put(&crtc->base);
469aee94f86SFrançois Tigeot 
470aee94f86SFrançois Tigeot 	schedule_work(&work->work);
471aee94f86SFrançois Tigeot }
472aee94f86SFrançois Tigeot 
473c0e85e96SFrançois Tigeot static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
4742c9916cdSFrançois Tigeot {
475c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
4762c9916cdSFrançois Tigeot 
477c0e85e96SFrançois Tigeot 	WARN_ON(!mutex_is_locked(&fbc->lock));
4782c9916cdSFrançois Tigeot 
479c0e85e96SFrançois Tigeot 	/* Calling cancel_work() here won't help due to the fact that the work
480c0e85e96SFrançois Tigeot 	 * function grabs fbc->lock. Just set scheduled to false so the work
481c0e85e96SFrançois Tigeot 	 * function can know it was cancelled. */
482c0e85e96SFrançois Tigeot 	fbc->work.scheduled = false;
483c0e85e96SFrançois Tigeot 
484c0e85e96SFrançois Tigeot 	if (fbc->active)
485c0e85e96SFrançois Tigeot 		intel_fbc_hw_deactivate(dev_priv);
486a05eeebfSFrançois Tigeot }
487a05eeebfSFrançois Tigeot 
4881487f786SFrançois Tigeot static bool multiple_pipes_ok(struct intel_crtc *crtc,
4891487f786SFrançois Tigeot 			      struct intel_plane_state *plane_state)
490a05eeebfSFrançois Tigeot {
4911487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
492c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
493c0e85e96SFrançois Tigeot 	enum i915_pipe pipe = crtc->pipe;
494a05eeebfSFrançois Tigeot 
495c0e85e96SFrançois Tigeot 	/* Don't even bother tracking anything we don't need. */
496c0e85e96SFrançois Tigeot 	if (!no_fbc_on_multiple_pipes(dev_priv))
497a05eeebfSFrançois Tigeot 		return true;
498a05eeebfSFrançois Tigeot 
4991487f786SFrançois Tigeot 	if (plane_state->visible)
500c0e85e96SFrançois Tigeot 		fbc->visible_pipes_mask |= (1 << pipe);
501c0e85e96SFrançois Tigeot 	else
502c0e85e96SFrançois Tigeot 		fbc->visible_pipes_mask &= ~(1 << pipe);
503a05eeebfSFrançois Tigeot 
504c0e85e96SFrançois Tigeot 	return (fbc->visible_pipes_mask & ~(1 << pipe)) != 0;
505a05eeebfSFrançois Tigeot }
506a05eeebfSFrançois Tigeot 
507a05eeebfSFrançois Tigeot static int find_compression_threshold(struct drm_i915_private *dev_priv,
508a05eeebfSFrançois Tigeot 				      struct drm_mm_node *node,
509a05eeebfSFrançois Tigeot 				      int size,
510a05eeebfSFrançois Tigeot 				      int fb_cpp)
511a05eeebfSFrançois Tigeot {
5128621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
513a05eeebfSFrançois Tigeot 	int compression_threshold = 1;
514a05eeebfSFrançois Tigeot 	int ret;
515352ff8bdSFrançois Tigeot 	u64 end;
516352ff8bdSFrançois Tigeot 
517352ff8bdSFrançois Tigeot 	/* The FBC hardware for BDW/SKL doesn't have access to the stolen
518352ff8bdSFrançois Tigeot 	 * reserved range size, so it always assumes the maximum (8mb) is used.
519352ff8bdSFrançois Tigeot 	 * If we enable FBC using a CFB on that memory range we'll get FIFO
520352ff8bdSFrançois Tigeot 	 * underruns, even if that range is not reserved by the BIOS. */
521aee94f86SFrançois Tigeot 	if (IS_BROADWELL(dev_priv) ||
522aee94f86SFrançois Tigeot 	    IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
5238621f407SFrançois Tigeot 		end = ggtt->stolen_size - 8 * 1024 * 1024;
524352ff8bdSFrançois Tigeot 	else
5258621f407SFrançois Tigeot 		end = ggtt->stolen_usable_size;
526a05eeebfSFrançois Tigeot 
527a05eeebfSFrançois Tigeot 	/* HACK: This code depends on what we will do in *_enable_fbc. If that
528a05eeebfSFrançois Tigeot 	 * code changes, this code needs to change as well.
529a05eeebfSFrançois Tigeot 	 *
530a05eeebfSFrançois Tigeot 	 * The enable_fbc code will attempt to use one of our 2 compression
531a05eeebfSFrançois Tigeot 	 * thresholds, therefore, in that case, we only have 1 resort.
532a05eeebfSFrançois Tigeot 	 */
533a05eeebfSFrançois Tigeot 
534a05eeebfSFrançois Tigeot 	/* Try to over-allocate to reduce reallocations and fragmentation. */
535352ff8bdSFrançois Tigeot 	ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size <<= 1,
536352ff8bdSFrançois Tigeot 						   4096, 0, end);
537a05eeebfSFrançois Tigeot 	if (ret == 0)
538a05eeebfSFrançois Tigeot 		return compression_threshold;
539a05eeebfSFrançois Tigeot 
540a05eeebfSFrançois Tigeot again:
541a05eeebfSFrançois Tigeot 	/* HW's ability to limit the CFB is 1:4 */
542a05eeebfSFrançois Tigeot 	if (compression_threshold > 4 ||
543a05eeebfSFrançois Tigeot 	    (fb_cpp == 2 && compression_threshold == 2))
544a05eeebfSFrançois Tigeot 		return 0;
545a05eeebfSFrançois Tigeot 
546352ff8bdSFrançois Tigeot 	ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1,
547352ff8bdSFrançois Tigeot 						   4096, 0, end);
548a05eeebfSFrançois Tigeot 	if (ret && INTEL_INFO(dev_priv)->gen <= 4) {
549a05eeebfSFrançois Tigeot 		return 0;
550a05eeebfSFrançois Tigeot 	} else if (ret) {
551a05eeebfSFrançois Tigeot 		compression_threshold <<= 1;
552a05eeebfSFrançois Tigeot 		goto again;
553a05eeebfSFrançois Tigeot 	} else {
554a05eeebfSFrançois Tigeot 		return compression_threshold;
555a05eeebfSFrançois Tigeot 	}
556a05eeebfSFrançois Tigeot }
557a05eeebfSFrançois Tigeot 
558aee94f86SFrançois Tigeot static int intel_fbc_alloc_cfb(struct intel_crtc *crtc)
559a05eeebfSFrançois Tigeot {
560303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
561c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
562aee94f86SFrançois Tigeot 	struct drm_mm_node *compressed_llb = NULL;
563aee94f86SFrançois Tigeot 	int size, fb_cpp, ret;
564aee94f86SFrançois Tigeot 
565c0e85e96SFrançois Tigeot 	WARN_ON(drm_mm_node_allocated(&fbc->compressed_fb));
566aee94f86SFrançois Tigeot 
567c0e85e96SFrançois Tigeot 	size = intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache);
568c0e85e96SFrançois Tigeot 	fb_cpp = drm_format_plane_cpp(fbc->state_cache.fb.pixel_format, 0);
569a05eeebfSFrançois Tigeot 
570c0e85e96SFrançois Tigeot 	ret = find_compression_threshold(dev_priv, &fbc->compressed_fb,
571a05eeebfSFrançois Tigeot 					 size, fb_cpp);
572a05eeebfSFrançois Tigeot 	if (!ret)
573a05eeebfSFrançois Tigeot 		goto err_llb;
574a05eeebfSFrançois Tigeot 	else if (ret > 1) {
575a05eeebfSFrançois Tigeot 		DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
576a05eeebfSFrançois Tigeot 
577a05eeebfSFrançois Tigeot 	}
578a05eeebfSFrançois Tigeot 
579c0e85e96SFrançois Tigeot 	fbc->threshold = ret;
580a05eeebfSFrançois Tigeot 
581a05eeebfSFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 5)
582c0e85e96SFrançois Tigeot 		I915_WRITE(ILK_DPFC_CB_BASE, fbc->compressed_fb.start);
583a05eeebfSFrançois Tigeot 	else if (IS_GM45(dev_priv)) {
584c0e85e96SFrançois Tigeot 		I915_WRITE(DPFC_CB_BASE, fbc->compressed_fb.start);
585a05eeebfSFrançois Tigeot 	} else {
586a05eeebfSFrançois Tigeot 		compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL);
587a05eeebfSFrançois Tigeot 		if (!compressed_llb)
588a05eeebfSFrançois Tigeot 			goto err_fb;
589a05eeebfSFrançois Tigeot 
590a05eeebfSFrançois Tigeot 		ret = i915_gem_stolen_insert_node(dev_priv, compressed_llb,
591a05eeebfSFrançois Tigeot 						  4096, 4096);
592a05eeebfSFrançois Tigeot 		if (ret)
593a05eeebfSFrançois Tigeot 			goto err_fb;
594a05eeebfSFrançois Tigeot 
595c0e85e96SFrançois Tigeot 		fbc->compressed_llb = compressed_llb;
596a05eeebfSFrançois Tigeot 
597a05eeebfSFrançois Tigeot 		I915_WRITE(FBC_CFB_BASE,
598c0e85e96SFrançois Tigeot 			   dev_priv->mm.stolen_base + fbc->compressed_fb.start);
599a05eeebfSFrançois Tigeot 		I915_WRITE(FBC_LL_BASE,
600a05eeebfSFrançois Tigeot 			   dev_priv->mm.stolen_base + compressed_llb->start);
601a05eeebfSFrançois Tigeot 	}
602a05eeebfSFrançois Tigeot 
603f77dbd6cSFrançois Tigeot 	DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
604c0e85e96SFrançois Tigeot 		      fbc->compressed_fb.size, fbc->threshold);
605a05eeebfSFrançois Tigeot 
606a05eeebfSFrançois Tigeot 	return 0;
607a05eeebfSFrançois Tigeot 
608a05eeebfSFrançois Tigeot err_fb:
609a05eeebfSFrançois Tigeot 	kfree(compressed_llb);
610c0e85e96SFrançois Tigeot 	i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb);
611a05eeebfSFrançois Tigeot err_llb:
612a05eeebfSFrançois Tigeot 	pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
613a05eeebfSFrançois Tigeot 	return -ENOSPC;
614a05eeebfSFrançois Tigeot }
615a05eeebfSFrançois Tigeot 
616a05eeebfSFrançois Tigeot static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
617a05eeebfSFrançois Tigeot {
618c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
619a05eeebfSFrançois Tigeot 
620c0e85e96SFrançois Tigeot 	if (drm_mm_node_allocated(&fbc->compressed_fb))
621c0e85e96SFrançois Tigeot 		i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb);
622c0e85e96SFrançois Tigeot 
623c0e85e96SFrançois Tigeot 	if (fbc->compressed_llb) {
624c0e85e96SFrançois Tigeot 		i915_gem_stolen_remove_node(dev_priv, fbc->compressed_llb);
625c0e85e96SFrançois Tigeot 		kfree(fbc->compressed_llb);
626a05eeebfSFrançois Tigeot 	}
627a05eeebfSFrançois Tigeot }
628a05eeebfSFrançois Tigeot 
629a05eeebfSFrançois Tigeot void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
630a05eeebfSFrançois Tigeot {
631c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
632c0e85e96SFrançois Tigeot 
633352ff8bdSFrançois Tigeot 	if (!fbc_supported(dev_priv))
634a05eeebfSFrançois Tigeot 		return;
635a05eeebfSFrançois Tigeot 
636c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
637a05eeebfSFrançois Tigeot 	__intel_fbc_cleanup_cfb(dev_priv);
638c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
639a05eeebfSFrançois Tigeot }
640a05eeebfSFrançois Tigeot 
641352ff8bdSFrançois Tigeot static bool stride_is_valid(struct drm_i915_private *dev_priv,
642352ff8bdSFrançois Tigeot 			    unsigned int stride)
643352ff8bdSFrançois Tigeot {
644352ff8bdSFrançois Tigeot 	/* These should have been caught earlier. */
645352ff8bdSFrançois Tigeot 	WARN_ON(stride < 512);
646352ff8bdSFrançois Tigeot 	WARN_ON((stride & (64 - 1)) != 0);
647352ff8bdSFrançois Tigeot 
648352ff8bdSFrançois Tigeot 	/* Below are the additional FBC restrictions. */
649352ff8bdSFrançois Tigeot 
650352ff8bdSFrançois Tigeot 	if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv))
651352ff8bdSFrançois Tigeot 		return stride == 4096 || stride == 8192;
652352ff8bdSFrançois Tigeot 
653352ff8bdSFrançois Tigeot 	if (IS_GEN4(dev_priv) && !IS_G4X(dev_priv) && stride < 2048)
654352ff8bdSFrançois Tigeot 		return false;
655352ff8bdSFrançois Tigeot 
656352ff8bdSFrançois Tigeot 	if (stride > 16384)
657352ff8bdSFrançois Tigeot 		return false;
658352ff8bdSFrançois Tigeot 
659352ff8bdSFrançois Tigeot 	return true;
660352ff8bdSFrançois Tigeot }
661352ff8bdSFrançois Tigeot 
662c0e85e96SFrançois Tigeot static bool pixel_format_is_valid(struct drm_i915_private *dev_priv,
663c0e85e96SFrançois Tigeot 				  uint32_t pixel_format)
664352ff8bdSFrançois Tigeot {
665c0e85e96SFrançois Tigeot 	switch (pixel_format) {
666352ff8bdSFrançois Tigeot 	case DRM_FORMAT_XRGB8888:
667352ff8bdSFrançois Tigeot 	case DRM_FORMAT_XBGR8888:
668352ff8bdSFrançois Tigeot 		return true;
669352ff8bdSFrançois Tigeot 	case DRM_FORMAT_XRGB1555:
670352ff8bdSFrançois Tigeot 	case DRM_FORMAT_RGB565:
671352ff8bdSFrançois Tigeot 		/* 16bpp not supported on gen2 */
672c0e85e96SFrançois Tigeot 		if (IS_GEN2(dev_priv))
673352ff8bdSFrançois Tigeot 			return false;
674352ff8bdSFrançois Tigeot 		/* WaFbcOnly1to1Ratio:ctg */
675352ff8bdSFrançois Tigeot 		if (IS_G4X(dev_priv))
676352ff8bdSFrançois Tigeot 			return false;
677352ff8bdSFrançois Tigeot 		return true;
678352ff8bdSFrançois Tigeot 	default:
679352ff8bdSFrançois Tigeot 		return false;
680352ff8bdSFrançois Tigeot 	}
681352ff8bdSFrançois Tigeot }
682352ff8bdSFrançois Tigeot 
683352ff8bdSFrançois Tigeot /*
684352ff8bdSFrançois Tigeot  * For some reason, the hardware tracking starts looking at whatever we
685352ff8bdSFrançois Tigeot  * programmed as the display plane base address register. It does not look at
686352ff8bdSFrançois Tigeot  * the X and Y offset registers. That's why we look at the crtc->adjusted{x,y}
687352ff8bdSFrançois Tigeot  * variables instead of just looking at the pipe/plane size.
688352ff8bdSFrançois Tigeot  */
689352ff8bdSFrançois Tigeot static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
690352ff8bdSFrançois Tigeot {
691303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
692c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
693352ff8bdSFrançois Tigeot 	unsigned int effective_w, effective_h, max_w, max_h;
694352ff8bdSFrançois Tigeot 
695352ff8bdSFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
696352ff8bdSFrançois Tigeot 		max_w = 4096;
697352ff8bdSFrançois Tigeot 		max_h = 4096;
698352ff8bdSFrançois Tigeot 	} else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
699352ff8bdSFrançois Tigeot 		max_w = 4096;
700352ff8bdSFrançois Tigeot 		max_h = 2048;
701352ff8bdSFrançois Tigeot 	} else {
702352ff8bdSFrançois Tigeot 		max_w = 2048;
703352ff8bdSFrançois Tigeot 		max_h = 1536;
704352ff8bdSFrançois Tigeot 	}
705352ff8bdSFrançois Tigeot 
706c0e85e96SFrançois Tigeot 	intel_fbc_get_plane_source_size(&fbc->state_cache, &effective_w,
707c0e85e96SFrançois Tigeot 					&effective_h);
708352ff8bdSFrançois Tigeot 	effective_w += crtc->adjusted_x;
709352ff8bdSFrançois Tigeot 	effective_h += crtc->adjusted_y;
710352ff8bdSFrançois Tigeot 
711352ff8bdSFrançois Tigeot 	return effective_w <= max_w && effective_h <= max_h;
712a05eeebfSFrançois Tigeot }
713a05eeebfSFrançois Tigeot 
7141487f786SFrançois Tigeot static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
7151487f786SFrançois Tigeot 					 struct intel_crtc_state *crtc_state,
7161487f786SFrançois Tigeot 					 struct intel_plane_state *plane_state)
7172c9916cdSFrançois Tigeot {
718303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
719c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
720c0e85e96SFrançois Tigeot 	struct intel_fbc_state_cache *cache = &fbc->state_cache;
721c0e85e96SFrançois Tigeot 	struct drm_framebuffer *fb = plane_state->base.fb;
7222c9916cdSFrançois Tigeot 	struct drm_i915_gem_object *obj;
7232c9916cdSFrançois Tigeot 
724c0e85e96SFrançois Tigeot 	cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
725c0e85e96SFrançois Tigeot 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
726c0e85e96SFrançois Tigeot 		cache->crtc.hsw_bdw_pixel_rate =
727c0e85e96SFrançois Tigeot 			ilk_pipe_pixel_rate(crtc_state);
7282c9916cdSFrançois Tigeot 
729c0e85e96SFrançois Tigeot 	cache->plane.rotation = plane_state->base.rotation;
730c0e85e96SFrançois Tigeot 	cache->plane.src_w = drm_rect_width(&plane_state->src) >> 16;
731c0e85e96SFrançois Tigeot 	cache->plane.src_h = drm_rect_height(&plane_state->src) >> 16;
732c0e85e96SFrançois Tigeot 	cache->plane.visible = plane_state->visible;
733c0e85e96SFrançois Tigeot 
734c0e85e96SFrançois Tigeot 	if (!cache->plane.visible)
735aee94f86SFrançois Tigeot 		return;
736aee94f86SFrançois Tigeot 
737c0e85e96SFrançois Tigeot 	obj = intel_fb_obj(fb);
738c0e85e96SFrançois Tigeot 
739c0e85e96SFrançois Tigeot 	/* FIXME: We lack the proper locking here, so only run this on the
740c0e85e96SFrançois Tigeot 	 * platforms that need. */
7411487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 5, 6))
742c0e85e96SFrançois Tigeot 		cache->fb.ilk_ggtt_offset = i915_gem_obj_ggtt_offset(obj);
743c0e85e96SFrançois Tigeot 	cache->fb.pixel_format = fb->pixel_format;
744c0e85e96SFrançois Tigeot 	cache->fb.stride = fb->pitches[0];
745c0e85e96SFrançois Tigeot 	cache->fb.fence_reg = obj->fence_reg;
746c0e85e96SFrançois Tigeot 	cache->fb.tiling_mode = obj->tiling_mode;
747aee94f86SFrançois Tigeot }
748aee94f86SFrançois Tigeot 
749c0e85e96SFrançois Tigeot static bool intel_fbc_can_activate(struct intel_crtc *crtc)
750c0e85e96SFrançois Tigeot {
751303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
752c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
753c0e85e96SFrançois Tigeot 	struct intel_fbc_state_cache *cache = &fbc->state_cache;
7542c9916cdSFrançois Tigeot 
755c0e85e96SFrançois Tigeot 	if (!cache->plane.visible) {
756c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "primary plane not visible";
757c0e85e96SFrançois Tigeot 		return false;
758c0e85e96SFrançois Tigeot 	}
759c0e85e96SFrançois Tigeot 
760c0e85e96SFrançois Tigeot 	if ((cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) ||
761c0e85e96SFrançois Tigeot 	    (cache->crtc.mode_flags & DRM_MODE_FLAG_DBLSCAN)) {
762c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "incompatible mode";
763c0e85e96SFrançois Tigeot 		return false;
7642c9916cdSFrançois Tigeot 	}
7652c9916cdSFrançois Tigeot 
766aee94f86SFrançois Tigeot 	if (!intel_fbc_hw_tracking_covers_screen(crtc)) {
767c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "mode too large for compression";
768c0e85e96SFrançois Tigeot 		return false;
7692c9916cdSFrançois Tigeot 	}
7702c9916cdSFrançois Tigeot 
7712c9916cdSFrançois Tigeot 	/* The use of a CPU fence is mandatory in order to detect writes
7722c9916cdSFrançois Tigeot 	 * by the CPU to the scanout and trigger updates to the FBC.
7732c9916cdSFrançois Tigeot 	 */
774c0e85e96SFrançois Tigeot 	if (cache->fb.tiling_mode != I915_TILING_X ||
775c0e85e96SFrançois Tigeot 	    cache->fb.fence_reg == I915_FENCE_REG_NONE) {
776c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "framebuffer not tiled or fenced";
777c0e85e96SFrançois Tigeot 		return false;
7782c9916cdSFrançois Tigeot 	}
779a05eeebfSFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
7801dedbd3bSFrançois Tigeot 	    cache->plane.rotation != DRM_ROTATE_0) {
781c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "rotation unsupported";
782c0e85e96SFrançois Tigeot 		return false;
7832c9916cdSFrançois Tigeot 	}
7842c9916cdSFrançois Tigeot 
785c0e85e96SFrançois Tigeot 	if (!stride_is_valid(dev_priv, cache->fb.stride)) {
786c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "framebuffer stride not supported";
787c0e85e96SFrançois Tigeot 		return false;
788352ff8bdSFrançois Tigeot 	}
789352ff8bdSFrançois Tigeot 
790c0e85e96SFrançois Tigeot 	if (!pixel_format_is_valid(dev_priv, cache->fb.pixel_format)) {
791c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "pixel format is invalid";
792c0e85e96SFrançois Tigeot 		return false;
793352ff8bdSFrançois Tigeot 	}
794352ff8bdSFrançois Tigeot 
795352ff8bdSFrançois Tigeot 	/* WaFbcExceedCdClockThreshold:hsw,bdw */
796352ff8bdSFrançois Tigeot 	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
797c0e85e96SFrançois Tigeot 	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) {
798c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "pixel rate is too big";
799c0e85e96SFrançois Tigeot 		return false;
800352ff8bdSFrançois Tigeot 	}
801352ff8bdSFrançois Tigeot 
802aee94f86SFrançois Tigeot 	/* It is possible for the required CFB size change without a
803aee94f86SFrançois Tigeot 	 * crtc->disable + crtc->enable since it is possible to change the
804aee94f86SFrançois Tigeot 	 * stride without triggering a full modeset. Since we try to
805aee94f86SFrançois Tigeot 	 * over-allocate the CFB, there's a chance we may keep FBC enabled even
806aee94f86SFrançois Tigeot 	 * if this happens, but if we exceed the current CFB size we'll have to
807aee94f86SFrançois Tigeot 	 * disable FBC. Notice that it would be possible to disable FBC, wait
808aee94f86SFrançois Tigeot 	 * for a frame, free the stolen node, then try to reenable FBC in case
809aee94f86SFrançois Tigeot 	 * we didn't get any invalidate/deactivate calls, but this would require
810aee94f86SFrançois Tigeot 	 * a lot of tracking just for a specific case. If we conclude it's an
811aee94f86SFrançois Tigeot 	 * important case, we can implement it later. */
812c0e85e96SFrançois Tigeot 	if (intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) >
813c0e85e96SFrançois Tigeot 	    fbc->compressed_fb.size * fbc->threshold) {
814c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "CFB requirements changed";
815c0e85e96SFrançois Tigeot 		return false;
8162c9916cdSFrançois Tigeot 	}
8172c9916cdSFrançois Tigeot 
818c0e85e96SFrançois Tigeot 	return true;
819c0e85e96SFrançois Tigeot }
820c0e85e96SFrançois Tigeot 
821c0e85e96SFrançois Tigeot static bool intel_fbc_can_choose(struct intel_crtc *crtc)
822c0e85e96SFrançois Tigeot {
823303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
824c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
825c0e85e96SFrançois Tigeot 
8261487f786SFrançois Tigeot 	if (intel_vgpu_active(dev_priv)) {
827c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "VGPU is active";
828c0e85e96SFrançois Tigeot 		return false;
829c0e85e96SFrançois Tigeot 	}
830c0e85e96SFrançois Tigeot 
831c0e85e96SFrançois Tigeot 	if (!i915.enable_fbc) {
832303bf270SFrançois Tigeot 		fbc->no_fbc_reason = "disabled per module param or by default";
833c0e85e96SFrançois Tigeot 		return false;
834c0e85e96SFrançois Tigeot 	}
835c0e85e96SFrançois Tigeot 
836c0e85e96SFrançois Tigeot 	if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) {
837c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "no enabled pipes can have FBC";
838c0e85e96SFrançois Tigeot 		return false;
839c0e85e96SFrançois Tigeot 	}
840c0e85e96SFrançois Tigeot 
841c0e85e96SFrançois Tigeot 	if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) {
842c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "no enabled planes can have FBC";
843c0e85e96SFrançois Tigeot 		return false;
844c0e85e96SFrançois Tigeot 	}
845c0e85e96SFrançois Tigeot 
846c0e85e96SFrançois Tigeot 	return true;
847c0e85e96SFrançois Tigeot }
848c0e85e96SFrançois Tigeot 
849c0e85e96SFrançois Tigeot static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
850c0e85e96SFrançois Tigeot 				     struct intel_fbc_reg_params *params)
851c0e85e96SFrançois Tigeot {
852303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
853c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
854c0e85e96SFrançois Tigeot 	struct intel_fbc_state_cache *cache = &fbc->state_cache;
855c0e85e96SFrançois Tigeot 
856c0e85e96SFrançois Tigeot 	/* Since all our fields are integer types, use memset here so the
857c0e85e96SFrançois Tigeot 	 * comparison function can rely on memcmp because the padding will be
858c0e85e96SFrançois Tigeot 	 * zero. */
859c0e85e96SFrançois Tigeot 	memset(params, 0, sizeof(*params));
860c0e85e96SFrançois Tigeot 
861c0e85e96SFrançois Tigeot 	params->crtc.pipe = crtc->pipe;
862c0e85e96SFrançois Tigeot 	params->crtc.plane = crtc->plane;
863c0e85e96SFrançois Tigeot 	params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc);
864c0e85e96SFrançois Tigeot 
865c0e85e96SFrançois Tigeot 	params->fb.pixel_format = cache->fb.pixel_format;
866c0e85e96SFrançois Tigeot 	params->fb.stride = cache->fb.stride;
867c0e85e96SFrançois Tigeot 	params->fb.fence_reg = cache->fb.fence_reg;
868c0e85e96SFrançois Tigeot 
869c0e85e96SFrançois Tigeot 	params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
870c0e85e96SFrançois Tigeot 
871c0e85e96SFrançois Tigeot 	params->fb.ggtt_offset = cache->fb.ilk_ggtt_offset;
872c0e85e96SFrançois Tigeot }
873c0e85e96SFrançois Tigeot 
874c0e85e96SFrançois Tigeot static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
875c0e85e96SFrançois Tigeot 				       struct intel_fbc_reg_params *params2)
876c0e85e96SFrançois Tigeot {
877c0e85e96SFrançois Tigeot 	/* We can use this since intel_fbc_get_reg_params() does a memset. */
878c0e85e96SFrançois Tigeot 	return memcmp(params1, params2, sizeof(*params1)) == 0;
879c0e85e96SFrançois Tigeot }
880c0e85e96SFrançois Tigeot 
8811487f786SFrançois Tigeot void intel_fbc_pre_update(struct intel_crtc *crtc,
8821487f786SFrançois Tigeot 			  struct intel_crtc_state *crtc_state,
8831487f786SFrançois Tigeot 			  struct intel_plane_state *plane_state)
884c0e85e96SFrançois Tigeot {
885303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
886c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
887c0e85e96SFrançois Tigeot 
888c0e85e96SFrançois Tigeot 	if (!fbc_supported(dev_priv))
889c0e85e96SFrançois Tigeot 		return;
890c0e85e96SFrançois Tigeot 
891c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
892c0e85e96SFrançois Tigeot 
8931487f786SFrançois Tigeot 	if (!multiple_pipes_ok(crtc, plane_state)) {
894c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "more than one pipe active";
895c0e85e96SFrançois Tigeot 		goto deactivate;
896c0e85e96SFrançois Tigeot 	}
897c0e85e96SFrançois Tigeot 
898c0e85e96SFrançois Tigeot 	if (!fbc->enabled || fbc->crtc != crtc)
899c0e85e96SFrançois Tigeot 		goto unlock;
900c0e85e96SFrançois Tigeot 
9011487f786SFrançois Tigeot 	intel_fbc_update_state_cache(crtc, crtc_state, plane_state);
902c0e85e96SFrançois Tigeot 
903c0e85e96SFrançois Tigeot deactivate:
904c0e85e96SFrançois Tigeot 	intel_fbc_deactivate(dev_priv);
905c0e85e96SFrançois Tigeot unlock:
906c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
907c0e85e96SFrançois Tigeot }
908c0e85e96SFrançois Tigeot 
909c0e85e96SFrançois Tigeot static void __intel_fbc_post_update(struct intel_crtc *crtc)
910c0e85e96SFrançois Tigeot {
911303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
912c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
913c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params old_params;
914c0e85e96SFrançois Tigeot 
915c0e85e96SFrançois Tigeot 	WARN_ON(!mutex_is_locked(&fbc->lock));
916c0e85e96SFrançois Tigeot 
917c0e85e96SFrançois Tigeot 	if (!fbc->enabled || fbc->crtc != crtc)
918c0e85e96SFrançois Tigeot 		return;
919c0e85e96SFrançois Tigeot 
920c0e85e96SFrançois Tigeot 	if (!intel_fbc_can_activate(crtc)) {
921c0e85e96SFrançois Tigeot 		WARN_ON(fbc->active);
922c0e85e96SFrançois Tigeot 		return;
923c0e85e96SFrançois Tigeot 	}
924c0e85e96SFrançois Tigeot 
925c0e85e96SFrançois Tigeot 	old_params = fbc->params;
926c0e85e96SFrançois Tigeot 	intel_fbc_get_reg_params(crtc, &fbc->params);
927c0e85e96SFrançois Tigeot 
9282c9916cdSFrançois Tigeot 	/* If the scanout has not changed, don't modify the FBC settings.
9292c9916cdSFrançois Tigeot 	 * Note that we make the fundamental assumption that the fb->obj
9302c9916cdSFrançois Tigeot 	 * cannot be unpinned (and have its GTT offset and fence revoked)
9312c9916cdSFrançois Tigeot 	 * without first being decoupled from the scanout and FBC disabled.
9322c9916cdSFrançois Tigeot 	 */
933c0e85e96SFrançois Tigeot 	if (fbc->active &&
934c0e85e96SFrançois Tigeot 	    intel_fbc_reg_params_equal(&old_params, &fbc->params))
9352c9916cdSFrançois Tigeot 		return;
9362c9916cdSFrançois Tigeot 
937c0e85e96SFrançois Tigeot 	intel_fbc_deactivate(dev_priv);
938aee94f86SFrançois Tigeot 	intel_fbc_schedule_activation(crtc);
939c0e85e96SFrançois Tigeot 	fbc->no_fbc_reason = "FBC enabled (active or scheduled)";
940a05eeebfSFrançois Tigeot }
941a05eeebfSFrançois Tigeot 
942c0e85e96SFrançois Tigeot void intel_fbc_post_update(struct intel_crtc *crtc)
943a05eeebfSFrançois Tigeot {
944303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
945c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
946aee94f86SFrançois Tigeot 
947352ff8bdSFrançois Tigeot 	if (!fbc_supported(dev_priv))
948a05eeebfSFrançois Tigeot 		return;
949a05eeebfSFrançois Tigeot 
950c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
951c0e85e96SFrançois Tigeot 	__intel_fbc_post_update(crtc);
952c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
953c0e85e96SFrançois Tigeot }
954c0e85e96SFrançois Tigeot 
955c0e85e96SFrançois Tigeot static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc)
956c0e85e96SFrançois Tigeot {
957c0e85e96SFrançois Tigeot 	if (fbc->enabled)
958c0e85e96SFrançois Tigeot 		return to_intel_plane(fbc->crtc->base.primary)->frontbuffer_bit;
959c0e85e96SFrançois Tigeot 	else
960c0e85e96SFrançois Tigeot 		return fbc->possible_framebuffer_bits;
9612c9916cdSFrançois Tigeot }
9622c9916cdSFrançois Tigeot 
963477eb7f9SFrançois Tigeot void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
964477eb7f9SFrançois Tigeot 			  unsigned int frontbuffer_bits,
965477eb7f9SFrançois Tigeot 			  enum fb_op_origin origin)
966477eb7f9SFrançois Tigeot {
967c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
968477eb7f9SFrançois Tigeot 
969352ff8bdSFrançois Tigeot 	if (!fbc_supported(dev_priv))
970a05eeebfSFrançois Tigeot 		return;
971a05eeebfSFrançois Tigeot 
972c0e85e96SFrançois Tigeot 	if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP)
973477eb7f9SFrançois Tigeot 		return;
974477eb7f9SFrançois Tigeot 
975c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
976a05eeebfSFrançois Tigeot 
977c0e85e96SFrançois Tigeot 	fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits;
978477eb7f9SFrançois Tigeot 
979c0e85e96SFrançois Tigeot 	if (fbc->enabled && fbc->busy_bits)
980c0e85e96SFrançois Tigeot 		intel_fbc_deactivate(dev_priv);
981477eb7f9SFrançois Tigeot 
982c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
983477eb7f9SFrançois Tigeot }
984477eb7f9SFrançois Tigeot 
985477eb7f9SFrançois Tigeot void intel_fbc_flush(struct drm_i915_private *dev_priv,
986a05eeebfSFrançois Tigeot 		     unsigned int frontbuffer_bits, enum fb_op_origin origin)
987477eb7f9SFrançois Tigeot {
988c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
989c0e85e96SFrançois Tigeot 
990352ff8bdSFrançois Tigeot 	if (!fbc_supported(dev_priv))
991477eb7f9SFrançois Tigeot 		return;
992477eb7f9SFrançois Tigeot 
993c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
994a05eeebfSFrançois Tigeot 
995c0e85e96SFrançois Tigeot 	fbc->busy_bits &= ~frontbuffer_bits;
996477eb7f9SFrançois Tigeot 
9971487f786SFrançois Tigeot 	if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP)
9981487f786SFrançois Tigeot 		goto out;
9991487f786SFrançois Tigeot 
1000c0e85e96SFrançois Tigeot 	if (!fbc->busy_bits && fbc->enabled &&
1001c0e85e96SFrançois Tigeot 	    (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) {
1002c0e85e96SFrançois Tigeot 		if (fbc->active)
1003aee94f86SFrançois Tigeot 			intel_fbc_recompress(dev_priv);
1004c0e85e96SFrançois Tigeot 		else
1005c0e85e96SFrançois Tigeot 			__intel_fbc_post_update(fbc->crtc);
1006c0e85e96SFrançois Tigeot 	}
1007c0e85e96SFrançois Tigeot 
10081487f786SFrançois Tigeot out:
1009c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1010c0e85e96SFrançois Tigeot }
1011c0e85e96SFrançois Tigeot 
1012c0e85e96SFrançois Tigeot /**
1013c0e85e96SFrançois Tigeot  * intel_fbc_choose_crtc - select a CRTC to enable FBC on
1014c0e85e96SFrançois Tigeot  * @dev_priv: i915 device instance
1015c0e85e96SFrançois Tigeot  * @state: the atomic state structure
1016c0e85e96SFrançois Tigeot  *
1017c0e85e96SFrançois Tigeot  * This function looks at the proposed state for CRTCs and planes, then chooses
1018c0e85e96SFrançois Tigeot  * which pipe is going to have FBC by setting intel_crtc_state->enable_fbc to
1019c0e85e96SFrançois Tigeot  * true.
1020c0e85e96SFrançois Tigeot  *
1021c0e85e96SFrançois Tigeot  * Later, intel_fbc_enable is going to look for state->enable_fbc and then maybe
1022c0e85e96SFrançois Tigeot  * enable FBC for the chosen CRTC. If it does, it will set dev_priv->fbc.crtc.
1023c0e85e96SFrançois Tigeot  */
1024c0e85e96SFrançois Tigeot void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv,
1025c0e85e96SFrançois Tigeot 			   struct drm_atomic_state *state)
1026c0e85e96SFrançois Tigeot {
1027c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1028c0e85e96SFrançois Tigeot 	struct drm_crtc *crtc;
1029c0e85e96SFrançois Tigeot 	struct drm_crtc_state *crtc_state;
1030c0e85e96SFrançois Tigeot 	struct drm_plane *plane;
1031c0e85e96SFrançois Tigeot 	struct drm_plane_state *plane_state;
1032c0e85e96SFrançois Tigeot 	bool fbc_crtc_present = false;
1033c0e85e96SFrançois Tigeot 	int i, j;
1034c0e85e96SFrançois Tigeot 
1035c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1036c0e85e96SFrançois Tigeot 
1037c0e85e96SFrançois Tigeot 	for_each_crtc_in_state(state, crtc, crtc_state, i) {
1038c0e85e96SFrançois Tigeot 		if (fbc->crtc == to_intel_crtc(crtc)) {
1039c0e85e96SFrançois Tigeot 			fbc_crtc_present = true;
1040c0e85e96SFrançois Tigeot 			break;
1041c0e85e96SFrançois Tigeot 		}
1042c0e85e96SFrançois Tigeot 	}
1043c0e85e96SFrançois Tigeot 	/* This atomic commit doesn't involve the CRTC currently tied to FBC. */
1044c0e85e96SFrançois Tigeot 	if (!fbc_crtc_present && fbc->crtc != NULL)
1045c0e85e96SFrançois Tigeot 		goto out;
1046c0e85e96SFrançois Tigeot 
1047c0e85e96SFrançois Tigeot 	/* Simply choose the first CRTC that is compatible and has a visible
1048c0e85e96SFrançois Tigeot 	 * plane. We could go for fancier schemes such as checking the plane
1049c0e85e96SFrançois Tigeot 	 * size, but this would just affect the few platforms that don't tie FBC
1050c0e85e96SFrançois Tigeot 	 * to pipe or plane A. */
1051c0e85e96SFrançois Tigeot 	for_each_plane_in_state(state, plane, plane_state, i) {
1052c0e85e96SFrançois Tigeot 		struct intel_plane_state *intel_plane_state =
1053c0e85e96SFrançois Tigeot 			to_intel_plane_state(plane_state);
1054c0e85e96SFrançois Tigeot 
1055c0e85e96SFrançois Tigeot 		if (!intel_plane_state->visible)
1056c0e85e96SFrançois Tigeot 			continue;
1057c0e85e96SFrançois Tigeot 
1058c0e85e96SFrançois Tigeot 		for_each_crtc_in_state(state, crtc, crtc_state, j) {
1059c0e85e96SFrançois Tigeot 			struct intel_crtc_state *intel_crtc_state =
1060c0e85e96SFrançois Tigeot 				to_intel_crtc_state(crtc_state);
1061c0e85e96SFrançois Tigeot 
1062c0e85e96SFrançois Tigeot 			if (plane_state->crtc != crtc)
1063c0e85e96SFrançois Tigeot 				continue;
1064c0e85e96SFrançois Tigeot 
1065c0e85e96SFrançois Tigeot 			if (!intel_fbc_can_choose(to_intel_crtc(crtc)))
1066c0e85e96SFrançois Tigeot 				break;
1067c0e85e96SFrançois Tigeot 
1068c0e85e96SFrançois Tigeot 			intel_crtc_state->enable_fbc = true;
1069c0e85e96SFrançois Tigeot 			goto out;
1070aee94f86SFrançois Tigeot 		}
1071a05eeebfSFrançois Tigeot 	}
1072a05eeebfSFrançois Tigeot 
1073c0e85e96SFrançois Tigeot out:
1074c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1075477eb7f9SFrançois Tigeot }
1076477eb7f9SFrançois Tigeot 
10772c9916cdSFrançois Tigeot /**
1078aee94f86SFrançois Tigeot  * intel_fbc_enable: tries to enable FBC on the CRTC
1079aee94f86SFrançois Tigeot  * @crtc: the CRTC
1080*87df8fc6SFrançois Tigeot  * @crtc_state: corresponding &drm_crtc_state for @crtc
1081*87df8fc6SFrançois Tigeot  * @plane_state: corresponding &drm_plane_state for the primary plane of @crtc
1082aee94f86SFrançois Tigeot  *
1083c0e85e96SFrançois Tigeot  * This function checks if the given CRTC was chosen for FBC, then enables it if
1084c0e85e96SFrançois Tigeot  * possible. Notice that it doesn't activate FBC. It is valid to call
1085c0e85e96SFrançois Tigeot  * intel_fbc_enable multiple times for the same pipe without an
1086c0e85e96SFrançois Tigeot  * intel_fbc_disable in the middle, as long as it is deactivated.
1087aee94f86SFrançois Tigeot  */
10881487f786SFrançois Tigeot void intel_fbc_enable(struct intel_crtc *crtc,
10891487f786SFrançois Tigeot 		      struct intel_crtc_state *crtc_state,
10901487f786SFrançois Tigeot 		      struct intel_plane_state *plane_state)
1091aee94f86SFrançois Tigeot {
1092303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1093c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1094aee94f86SFrançois Tigeot 
1095aee94f86SFrançois Tigeot 	if (!fbc_supported(dev_priv))
1096aee94f86SFrançois Tigeot 		return;
1097aee94f86SFrançois Tigeot 
1098c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1099aee94f86SFrançois Tigeot 
1100c0e85e96SFrançois Tigeot 	if (fbc->enabled) {
1101c0e85e96SFrançois Tigeot 		WARN_ON(fbc->crtc == NULL);
1102c0e85e96SFrançois Tigeot 		if (fbc->crtc == crtc) {
11031487f786SFrançois Tigeot 			WARN_ON(!crtc_state->enable_fbc);
1104c0e85e96SFrançois Tigeot 			WARN_ON(fbc->active);
1105c0e85e96SFrançois Tigeot 		}
1106aee94f86SFrançois Tigeot 		goto out;
1107aee94f86SFrançois Tigeot 	}
1108aee94f86SFrançois Tigeot 
11091487f786SFrançois Tigeot 	if (!crtc_state->enable_fbc)
1110aee94f86SFrançois Tigeot 		goto out;
1111aee94f86SFrançois Tigeot 
1112c0e85e96SFrançois Tigeot 	WARN_ON(fbc->active);
1113c0e85e96SFrançois Tigeot 	WARN_ON(fbc->crtc != NULL);
1114aee94f86SFrançois Tigeot 
11151487f786SFrançois Tigeot 	intel_fbc_update_state_cache(crtc, crtc_state, plane_state);
1116aee94f86SFrançois Tigeot 	if (intel_fbc_alloc_cfb(crtc)) {
1117c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "not enough stolen memory";
1118aee94f86SFrançois Tigeot 		goto out;
1119aee94f86SFrançois Tigeot 	}
1120aee94f86SFrançois Tigeot 
1121aee94f86SFrançois Tigeot 	DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe));
1122c0e85e96SFrançois Tigeot 	fbc->no_fbc_reason = "FBC enabled but not active yet\n";
1123aee94f86SFrançois Tigeot 
1124c0e85e96SFrançois Tigeot 	fbc->enabled = true;
1125c0e85e96SFrançois Tigeot 	fbc->crtc = crtc;
1126aee94f86SFrançois Tigeot out:
1127c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1128aee94f86SFrançois Tigeot }
1129aee94f86SFrançois Tigeot 
1130aee94f86SFrançois Tigeot /**
1131aee94f86SFrançois Tigeot  * __intel_fbc_disable - disable FBC
1132aee94f86SFrançois Tigeot  * @dev_priv: i915 device instance
1133aee94f86SFrançois Tigeot  *
1134aee94f86SFrançois Tigeot  * This is the low level function that actually disables FBC. Callers should
1135aee94f86SFrançois Tigeot  * grab the FBC lock.
1136aee94f86SFrançois Tigeot  */
1137aee94f86SFrançois Tigeot static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
1138aee94f86SFrançois Tigeot {
1139c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1140c0e85e96SFrançois Tigeot 	struct intel_crtc *crtc = fbc->crtc;
1141aee94f86SFrançois Tigeot 
1142c0e85e96SFrançois Tigeot 	WARN_ON(!mutex_is_locked(&fbc->lock));
1143c0e85e96SFrançois Tigeot 	WARN_ON(!fbc->enabled);
1144c0e85e96SFrançois Tigeot 	WARN_ON(fbc->active);
1145c0e85e96SFrançois Tigeot 	WARN_ON(crtc->active);
1146aee94f86SFrançois Tigeot 
1147aee94f86SFrançois Tigeot 	DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe));
1148aee94f86SFrançois Tigeot 
1149aee94f86SFrançois Tigeot 	__intel_fbc_cleanup_cfb(dev_priv);
1150aee94f86SFrançois Tigeot 
1151c0e85e96SFrançois Tigeot 	fbc->enabled = false;
1152c0e85e96SFrançois Tigeot 	fbc->crtc = NULL;
1153aee94f86SFrançois Tigeot }
1154aee94f86SFrançois Tigeot 
1155aee94f86SFrançois Tigeot /**
1156c0e85e96SFrançois Tigeot  * intel_fbc_disable - disable FBC if it's associated with crtc
1157aee94f86SFrançois Tigeot  * @crtc: the CRTC
1158aee94f86SFrançois Tigeot  *
1159aee94f86SFrançois Tigeot  * This function disables FBC if it's associated with the provided CRTC.
1160aee94f86SFrançois Tigeot  */
1161c0e85e96SFrançois Tigeot void intel_fbc_disable(struct intel_crtc *crtc)
1162aee94f86SFrançois Tigeot {
1163303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1164c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1165aee94f86SFrançois Tigeot 
1166aee94f86SFrançois Tigeot 	if (!fbc_supported(dev_priv))
1167aee94f86SFrançois Tigeot 		return;
1168aee94f86SFrançois Tigeot 
1169c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1170c0e85e96SFrançois Tigeot 	if (fbc->crtc == crtc) {
1171c0e85e96SFrançois Tigeot 		WARN_ON(!fbc->enabled);
1172c0e85e96SFrançois Tigeot 		WARN_ON(fbc->active);
1173aee94f86SFrançois Tigeot 		__intel_fbc_disable(dev_priv);
1174aee94f86SFrançois Tigeot 	}
1175c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1176c0e85e96SFrançois Tigeot 
1177c0e85e96SFrançois Tigeot 	cancel_work_sync(&fbc->work.work);
1178aee94f86SFrançois Tigeot }
1179aee94f86SFrançois Tigeot 
1180aee94f86SFrançois Tigeot /**
1181c0e85e96SFrançois Tigeot  * intel_fbc_global_disable - globally disable FBC
1182aee94f86SFrançois Tigeot  * @dev_priv: i915 device instance
1183aee94f86SFrançois Tigeot  *
1184aee94f86SFrançois Tigeot  * This function disables FBC regardless of which CRTC is associated with it.
1185aee94f86SFrançois Tigeot  */
1186c0e85e96SFrançois Tigeot void intel_fbc_global_disable(struct drm_i915_private *dev_priv)
1187aee94f86SFrançois Tigeot {
1188c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1189c0e85e96SFrançois Tigeot 
1190aee94f86SFrançois Tigeot 	if (!fbc_supported(dev_priv))
1191aee94f86SFrançois Tigeot 		return;
1192aee94f86SFrançois Tigeot 
1193c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1194c0e85e96SFrançois Tigeot 	if (fbc->enabled)
1195aee94f86SFrançois Tigeot 		__intel_fbc_disable(dev_priv);
1196c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1197c0e85e96SFrançois Tigeot 
1198c0e85e96SFrançois Tigeot 	cancel_work_sync(&fbc->work.work);
1199c0e85e96SFrançois Tigeot }
1200c0e85e96SFrançois Tigeot 
1201c0e85e96SFrançois Tigeot /**
1202c0e85e96SFrançois Tigeot  * intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking
1203c0e85e96SFrançois Tigeot  * @dev_priv: i915 device instance
1204c0e85e96SFrançois Tigeot  *
1205c0e85e96SFrançois Tigeot  * The FBC code needs to track CRTC visibility since the older platforms can't
1206c0e85e96SFrançois Tigeot  * have FBC enabled while multiple pipes are used. This function does the
1207c0e85e96SFrançois Tigeot  * initial setup at driver load to make sure FBC is matching the real hardware.
1208c0e85e96SFrançois Tigeot  */
1209c0e85e96SFrançois Tigeot void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv)
1210c0e85e96SFrançois Tigeot {
1211c0e85e96SFrançois Tigeot 	struct intel_crtc *crtc;
1212c0e85e96SFrançois Tigeot 
1213c0e85e96SFrançois Tigeot 	/* Don't even bother tracking anything if we don't need. */
1214c0e85e96SFrançois Tigeot 	if (!no_fbc_on_multiple_pipes(dev_priv))
1215c0e85e96SFrançois Tigeot 		return;
1216c0e85e96SFrançois Tigeot 
1217303bf270SFrançois Tigeot 	for_each_intel_crtc(&dev_priv->drm, crtc)
1218c0e85e96SFrançois Tigeot 		if (intel_crtc_active(&crtc->base) &&
1219c0e85e96SFrançois Tigeot 		    to_intel_plane_state(crtc->base.primary->state)->visible)
1220c0e85e96SFrançois Tigeot 			dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe);
1221aee94f86SFrançois Tigeot }
1222aee94f86SFrançois Tigeot 
12231487f786SFrançois Tigeot /*
12241487f786SFrançois Tigeot  * The DDX driver changes its behavior depending on the value it reads from
12251487f786SFrançois Tigeot  * i915.enable_fbc, so sanitize it by translating the default value into either
12261487f786SFrançois Tigeot  * 0 or 1 in order to allow it to know what's going on.
12271487f786SFrançois Tigeot  *
12281487f786SFrançois Tigeot  * Notice that this is done at driver initialization and we still allow user
12291487f786SFrançois Tigeot  * space to change the value during runtime without sanitizing it again. IGT
12301487f786SFrançois Tigeot  * relies on being able to change i915.enable_fbc at runtime.
12311487f786SFrançois Tigeot  */
12321487f786SFrançois Tigeot static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
12331487f786SFrançois Tigeot {
12341487f786SFrançois Tigeot 	if (i915.enable_fbc >= 0)
12351487f786SFrançois Tigeot 		return !!i915.enable_fbc;
12361487f786SFrançois Tigeot 
1237bf017597SFrançois Tigeot 	if (!HAS_FBC(dev_priv))
1238bf017597SFrançois Tigeot 		return 0;
1239bf017597SFrançois Tigeot 
12401487f786SFrançois Tigeot 	if (IS_BROADWELL(dev_priv))
12411487f786SFrançois Tigeot 		return 1;
12421487f786SFrançois Tigeot 
12431487f786SFrançois Tigeot 	return 0;
12441487f786SFrançois Tigeot }
12451487f786SFrançois Tigeot 
1246bf017597SFrançois Tigeot static bool need_fbc_vtd_wa(struct drm_i915_private *dev_priv)
1247bf017597SFrançois Tigeot {
1248bf017597SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU
1249bf017597SFrançois Tigeot 	/* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
1250bf017597SFrançois Tigeot 	if (intel_iommu_gfx_mapped &&
1251bf017597SFrançois Tigeot 	    (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))) {
1252bf017597SFrançois Tigeot 		DRM_INFO("Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n");
1253bf017597SFrançois Tigeot 		return true;
1254bf017597SFrançois Tigeot 	}
1255bf017597SFrançois Tigeot #endif
1256bf017597SFrançois Tigeot 
1257bf017597SFrançois Tigeot 	return false;
1258bf017597SFrançois Tigeot }
1259bf017597SFrançois Tigeot 
1260aee94f86SFrançois Tigeot /**
12612c9916cdSFrançois Tigeot  * intel_fbc_init - Initialize FBC
12622c9916cdSFrançois Tigeot  * @dev_priv: the i915 device
12632c9916cdSFrançois Tigeot  *
12642c9916cdSFrançois Tigeot  * This function might be called during PM init process.
12652c9916cdSFrançois Tigeot  */
12662c9916cdSFrançois Tigeot void intel_fbc_init(struct drm_i915_private *dev_priv)
12672c9916cdSFrançois Tigeot {
1268c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1269477eb7f9SFrançois Tigeot 	enum i915_pipe pipe;
1270477eb7f9SFrançois Tigeot 
1271c0e85e96SFrançois Tigeot 	INIT_WORK(&fbc->work.work, intel_fbc_work_fn);
1272c0e85e96SFrançois Tigeot 	lockinit(&fbc->lock, "i915fl", 0, LK_CANRECURSE);
1273c0e85e96SFrançois Tigeot 	fbc->enabled = false;
1274c0e85e96SFrançois Tigeot 	fbc->active = false;
1275c0e85e96SFrançois Tigeot 	fbc->work.scheduled = false;
1276a05eeebfSFrançois Tigeot 
1277bf017597SFrançois Tigeot 	if (need_fbc_vtd_wa(dev_priv))
1278bf017597SFrançois Tigeot 		mkwrite_device_info(dev_priv)->has_fbc = false;
1279bf017597SFrançois Tigeot 
12801487f786SFrançois Tigeot 	i915.enable_fbc = intel_sanitize_fbc_option(dev_priv);
12811487f786SFrançois Tigeot 	DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", i915.enable_fbc);
12821487f786SFrançois Tigeot 
12832c9916cdSFrançois Tigeot 	if (!HAS_FBC(dev_priv)) {
1284c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "unsupported by this chipset";
12852c9916cdSFrançois Tigeot 		return;
12862c9916cdSFrançois Tigeot 	}
12872c9916cdSFrançois Tigeot 
1288477eb7f9SFrançois Tigeot 	for_each_pipe(dev_priv, pipe) {
1289c0e85e96SFrançois Tigeot 		fbc->possible_framebuffer_bits |=
1290477eb7f9SFrançois Tigeot 				INTEL_FRONTBUFFER_PRIMARY(pipe);
1291477eb7f9SFrançois Tigeot 
1292aee94f86SFrançois Tigeot 		if (fbc_on_pipe_a_only(dev_priv))
1293477eb7f9SFrançois Tigeot 			break;
1294477eb7f9SFrançois Tigeot 	}
1295477eb7f9SFrançois Tigeot 
12962c9916cdSFrançois Tigeot 	/* This value was pulled out of someone's hat */
1297c0e85e96SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_GM45(dev_priv))
12982c9916cdSFrançois Tigeot 		I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
12992c9916cdSFrançois Tigeot 
1300aee94f86SFrançois Tigeot 	/* We still don't have any sort of hardware state readout for FBC, so
1301aee94f86SFrançois Tigeot 	 * deactivate it in case the BIOS activated it to make sure software
1302aee94f86SFrançois Tigeot 	 * matches the hardware state. */
1303c0e85e96SFrançois Tigeot 	if (intel_fbc_hw_is_active(dev_priv))
1304c0e85e96SFrançois Tigeot 		intel_fbc_hw_deactivate(dev_priv);
13052c9916cdSFrançois Tigeot }
1306