xref: /dflybsd-src/sys/dev/drm/i915/intel_fbc.c (revision 1e12ee3baa16120663cde9c6c4c8e92b69b00794)
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);
10771f41f3eSFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 7)
108aee94f86SFrançois Tigeot 		lines = min(lines, 2048);
109aee94f86SFrançois Tigeot 
110aee94f86SFrançois Tigeot 	/* Hardware needs the full buffer stride, not just the active area. */
111c0e85e96SFrançois Tigeot 	return lines * cache->fb.stride;
112aee94f86SFrançois Tigeot }
113aee94f86SFrançois Tigeot 
114aee94f86SFrançois Tigeot static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv)
1152c9916cdSFrançois Tigeot {
1162c9916cdSFrançois Tigeot 	u32 fbc_ctl;
1172c9916cdSFrançois Tigeot 
1182c9916cdSFrançois Tigeot 	/* Disable compression */
1192c9916cdSFrançois Tigeot 	fbc_ctl = I915_READ(FBC_CONTROL);
1202c9916cdSFrançois Tigeot 	if ((fbc_ctl & FBC_CTL_EN) == 0)
1212c9916cdSFrançois Tigeot 		return;
1222c9916cdSFrançois Tigeot 
1232c9916cdSFrançois Tigeot 	fbc_ctl &= ~FBC_CTL_EN;
1242c9916cdSFrançois Tigeot 	I915_WRITE(FBC_CONTROL, fbc_ctl);
1252c9916cdSFrançois Tigeot 
1262c9916cdSFrançois Tigeot 	/* Wait for compressing bit to clear */
1271487f786SFrançois Tigeot 	if (intel_wait_for_register(dev_priv,
1281487f786SFrançois Tigeot 				    FBC_STATUS, FBC_STAT_COMPRESSING, 0,
1291487f786SFrançois Tigeot 				    10)) {
1302c9916cdSFrançois Tigeot 		DRM_DEBUG_KMS("FBC idle timed out\n");
1312c9916cdSFrançois Tigeot 		return;
1322c9916cdSFrançois Tigeot 	}
1332c9916cdSFrançois Tigeot }
1342c9916cdSFrançois Tigeot 
135c0e85e96SFrançois Tigeot static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
1362c9916cdSFrançois Tigeot {
137c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
1382c9916cdSFrançois Tigeot 	int cfb_pitch;
1392c9916cdSFrançois Tigeot 	int i;
1402c9916cdSFrançois Tigeot 	u32 fbc_ctl;
1412c9916cdSFrançois Tigeot 
142477eb7f9SFrançois Tigeot 	/* Note: fbc.threshold == 1 for i8xx */
143c0e85e96SFrançois Tigeot 	cfb_pitch = params->cfb_size / FBC_LL_SIZE;
144c0e85e96SFrançois Tigeot 	if (params->fb.stride < cfb_pitch)
145c0e85e96SFrançois Tigeot 		cfb_pitch = params->fb.stride;
1462c9916cdSFrançois Tigeot 
1472c9916cdSFrançois Tigeot 	/* FBC_CTL wants 32B or 64B units */
148a05eeebfSFrançois Tigeot 	if (IS_GEN2(dev_priv))
1492c9916cdSFrançois Tigeot 		cfb_pitch = (cfb_pitch / 32) - 1;
1502c9916cdSFrançois Tigeot 	else
1512c9916cdSFrançois Tigeot 		cfb_pitch = (cfb_pitch / 64) - 1;
1522c9916cdSFrançois Tigeot 
1532c9916cdSFrançois Tigeot 	/* Clear old tags */
1542c9916cdSFrançois Tigeot 	for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
155352ff8bdSFrançois Tigeot 		I915_WRITE(FBC_TAG(i), 0);
1562c9916cdSFrançois Tigeot 
157a05eeebfSFrançois Tigeot 	if (IS_GEN4(dev_priv)) {
1582c9916cdSFrançois Tigeot 		u32 fbc_ctl2;
1592c9916cdSFrançois Tigeot 
1602c9916cdSFrançois Tigeot 		/* Set it up... */
1612c9916cdSFrançois Tigeot 		fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
162c0e85e96SFrançois Tigeot 		fbc_ctl2 |= FBC_CTL_PLANE(params->crtc.plane);
1632c9916cdSFrançois Tigeot 		I915_WRITE(FBC_CONTROL2, fbc_ctl2);
164c0e85e96SFrançois Tigeot 		I915_WRITE(FBC_FENCE_OFF, params->crtc.fence_y_offset);
1652c9916cdSFrançois Tigeot 	}
1662c9916cdSFrançois Tigeot 
1672c9916cdSFrançois Tigeot 	/* enable it... */
1682c9916cdSFrançois Tigeot 	fbc_ctl = I915_READ(FBC_CONTROL);
1692c9916cdSFrançois Tigeot 	fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT;
1702c9916cdSFrançois Tigeot 	fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
171a05eeebfSFrançois Tigeot 	if (IS_I945GM(dev_priv))
1722c9916cdSFrançois Tigeot 		fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
1732c9916cdSFrançois Tigeot 	fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
174c0e85e96SFrançois Tigeot 	fbc_ctl |= params->fb.fence_reg;
1752c9916cdSFrançois Tigeot 	I915_WRITE(FBC_CONTROL, fbc_ctl);
1762c9916cdSFrançois Tigeot }
1772c9916cdSFrançois Tigeot 
178aee94f86SFrançois Tigeot static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv)
1792c9916cdSFrançois Tigeot {
1802c9916cdSFrançois Tigeot 	return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
1812c9916cdSFrançois Tigeot }
1822c9916cdSFrançois Tigeot 
183c0e85e96SFrançois Tigeot static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
1842c9916cdSFrançois Tigeot {
185c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
1862c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
1872c9916cdSFrançois Tigeot 
188c0e85e96SFrançois Tigeot 	dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane) | DPFC_SR_EN;
189c0e85e96SFrançois Tigeot 	if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2)
1902c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
1912c9916cdSFrançois Tigeot 	else
1922c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
1932c9916cdSFrançois Tigeot 
194*1e12ee3bSFrançois Tigeot 	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
195*1e12ee3bSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg;
196c0e85e96SFrançois Tigeot 		I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
197*1e12ee3bSFrançois Tigeot 	} else {
198*1e12ee3bSFrançois Tigeot 		I915_WRITE(DPFC_FENCE_YOFF, 0);
199*1e12ee3bSFrançois Tigeot 	}
2002c9916cdSFrançois Tigeot 
2012c9916cdSFrançois Tigeot 	/* enable it... */
2022c9916cdSFrançois Tigeot 	I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
2032c9916cdSFrançois Tigeot }
2042c9916cdSFrançois Tigeot 
205aee94f86SFrançois Tigeot static void g4x_fbc_deactivate(struct drm_i915_private *dev_priv)
2062c9916cdSFrançois Tigeot {
2072c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
2082c9916cdSFrançois Tigeot 
2092c9916cdSFrançois Tigeot 	/* Disable compression */
2102c9916cdSFrançois Tigeot 	dpfc_ctl = I915_READ(DPFC_CONTROL);
2112c9916cdSFrançois Tigeot 	if (dpfc_ctl & DPFC_CTL_EN) {
2122c9916cdSFrançois Tigeot 		dpfc_ctl &= ~DPFC_CTL_EN;
2132c9916cdSFrançois Tigeot 		I915_WRITE(DPFC_CONTROL, dpfc_ctl);
2142c9916cdSFrançois Tigeot 	}
2152c9916cdSFrançois Tigeot }
2162c9916cdSFrançois Tigeot 
217aee94f86SFrançois Tigeot static bool g4x_fbc_is_active(struct drm_i915_private *dev_priv)
2182c9916cdSFrançois Tigeot {
2192c9916cdSFrançois Tigeot 	return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
2202c9916cdSFrançois Tigeot }
2212c9916cdSFrançois Tigeot 
222aee94f86SFrançois Tigeot /* This function forces a CFB recompression through the nuke operation. */
223aee94f86SFrançois Tigeot static void intel_fbc_recompress(struct drm_i915_private *dev_priv)
2242c9916cdSFrançois Tigeot {
225477eb7f9SFrançois Tigeot 	I915_WRITE(MSG_FBC_REND_STATE, FBC_REND_NUKE);
226477eb7f9SFrançois Tigeot 	POSTING_READ(MSG_FBC_REND_STATE);
2272c9916cdSFrançois Tigeot }
2282c9916cdSFrançois Tigeot 
229c0e85e96SFrançois Tigeot static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
2302c9916cdSFrançois Tigeot {
231c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
2322c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
233a05eeebfSFrançois Tigeot 	int threshold = dev_priv->fbc.threshold;
2342c9916cdSFrançois Tigeot 
235c0e85e96SFrançois Tigeot 	dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane);
236c0e85e96SFrançois Tigeot 	if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2)
237a05eeebfSFrançois Tigeot 		threshold++;
2382c9916cdSFrançois Tigeot 
239a05eeebfSFrançois Tigeot 	switch (threshold) {
2402c9916cdSFrançois Tigeot 	case 4:
2412c9916cdSFrançois Tigeot 	case 3:
2422c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_4X;
2432c9916cdSFrançois Tigeot 		break;
2442c9916cdSFrançois Tigeot 	case 2:
2452c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
2462c9916cdSFrançois Tigeot 		break;
2472c9916cdSFrançois Tigeot 	case 1:
2482c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
2492c9916cdSFrançois Tigeot 		break;
2502c9916cdSFrançois Tigeot 	}
251*1e12ee3bSFrançois Tigeot 
252*1e12ee3bSFrançois Tigeot 	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
2532c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_FENCE_EN;
254a05eeebfSFrançois Tigeot 		if (IS_GEN5(dev_priv))
255c0e85e96SFrançois Tigeot 			dpfc_ctl |= params->fb.fence_reg;
256*1e12ee3bSFrançois Tigeot 		if (IS_GEN6(dev_priv)) {
257*1e12ee3bSFrançois Tigeot 			I915_WRITE(SNB_DPFC_CTL_SA,
258*1e12ee3bSFrançois Tigeot 				   SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
259*1e12ee3bSFrançois Tigeot 			I915_WRITE(DPFC_CPU_FENCE_OFFSET,
260*1e12ee3bSFrançois Tigeot 				   params->crtc.fence_y_offset);
261*1e12ee3bSFrançois Tigeot 		}
262*1e12ee3bSFrançois Tigeot 	} else {
263*1e12ee3bSFrançois Tigeot 		if (IS_GEN6(dev_priv)) {
264*1e12ee3bSFrançois Tigeot 			I915_WRITE(SNB_DPFC_CTL_SA, 0);
265*1e12ee3bSFrançois Tigeot 			I915_WRITE(DPFC_CPU_FENCE_OFFSET, 0);
266*1e12ee3bSFrançois Tigeot 		}
267*1e12ee3bSFrançois Tigeot 	}
2682c9916cdSFrançois Tigeot 
269c0e85e96SFrançois Tigeot 	I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
270c0e85e96SFrançois Tigeot 	I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID);
2712c9916cdSFrançois Tigeot 	/* enable it... */
2722c9916cdSFrançois Tigeot 	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
2732c9916cdSFrançois Tigeot 
274aee94f86SFrançois Tigeot 	intel_fbc_recompress(dev_priv);
2752c9916cdSFrançois Tigeot }
2762c9916cdSFrançois Tigeot 
277aee94f86SFrançois Tigeot static void ilk_fbc_deactivate(struct drm_i915_private *dev_priv)
2782c9916cdSFrançois Tigeot {
2792c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
2802c9916cdSFrançois Tigeot 
2812c9916cdSFrançois Tigeot 	/* Disable compression */
2822c9916cdSFrançois Tigeot 	dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
2832c9916cdSFrançois Tigeot 	if (dpfc_ctl & DPFC_CTL_EN) {
2842c9916cdSFrançois Tigeot 		dpfc_ctl &= ~DPFC_CTL_EN;
2852c9916cdSFrançois Tigeot 		I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
2862c9916cdSFrançois Tigeot 	}
2872c9916cdSFrançois Tigeot }
2882c9916cdSFrançois Tigeot 
289aee94f86SFrançois Tigeot static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv)
2902c9916cdSFrançois Tigeot {
2912c9916cdSFrançois Tigeot 	return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
2922c9916cdSFrançois Tigeot }
2932c9916cdSFrançois Tigeot 
294c0e85e96SFrançois Tigeot static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
2952c9916cdSFrançois Tigeot {
296c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params *params = &dev_priv->fbc.params;
2972c9916cdSFrançois Tigeot 	u32 dpfc_ctl;
298a05eeebfSFrançois Tigeot 	int threshold = dev_priv->fbc.threshold;
2992c9916cdSFrançois Tigeot 
300a05eeebfSFrançois Tigeot 	dpfc_ctl = 0;
301a05eeebfSFrançois Tigeot 	if (IS_IVYBRIDGE(dev_priv))
302c0e85e96SFrançois Tigeot 		dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.plane);
3032c9916cdSFrançois Tigeot 
304c0e85e96SFrançois Tigeot 	if (drm_format_plane_cpp(params->fb.pixel_format, 0) == 2)
305a05eeebfSFrançois Tigeot 		threshold++;
306a05eeebfSFrançois Tigeot 
307a05eeebfSFrançois Tigeot 	switch (threshold) {
3082c9916cdSFrançois Tigeot 	case 4:
3092c9916cdSFrançois Tigeot 	case 3:
3102c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_4X;
3112c9916cdSFrançois Tigeot 		break;
3122c9916cdSFrançois Tigeot 	case 2:
3132c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_2X;
3142c9916cdSFrançois Tigeot 		break;
3152c9916cdSFrançois Tigeot 	case 1:
3162c9916cdSFrançois Tigeot 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
3172c9916cdSFrançois Tigeot 		break;
3182c9916cdSFrançois Tigeot 	}
3192c9916cdSFrançois Tigeot 
320*1e12ee3bSFrançois Tigeot 	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
3212c9916cdSFrançois Tigeot 		dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
322*1e12ee3bSFrançois Tigeot 		I915_WRITE(SNB_DPFC_CTL_SA,
323*1e12ee3bSFrançois Tigeot 			   SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
324*1e12ee3bSFrançois Tigeot 		I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
325*1e12ee3bSFrançois Tigeot 	} else {
326*1e12ee3bSFrançois Tigeot 		I915_WRITE(SNB_DPFC_CTL_SA,0);
327*1e12ee3bSFrançois Tigeot 		I915_WRITE(DPFC_CPU_FENCE_OFFSET, 0);
328*1e12ee3bSFrançois Tigeot 	}
3292c9916cdSFrançois Tigeot 
3302c9916cdSFrançois Tigeot 	if (dev_priv->fbc.false_color)
3312c9916cdSFrançois Tigeot 		dpfc_ctl |= FBC_CTL_FALSE_COLOR;
3322c9916cdSFrançois Tigeot 
333a05eeebfSFrançois Tigeot 	if (IS_IVYBRIDGE(dev_priv)) {
3342c9916cdSFrançois Tigeot 		/* WaFbcAsynchFlipDisableFbcQueue:ivb */
3352c9916cdSFrançois Tigeot 		I915_WRITE(ILK_DISPLAY_CHICKEN1,
3362c9916cdSFrançois Tigeot 			   I915_READ(ILK_DISPLAY_CHICKEN1) |
3372c9916cdSFrançois Tigeot 			   ILK_FBCQ_DIS);
338352ff8bdSFrançois Tigeot 	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
3392c9916cdSFrançois Tigeot 		/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
340c0e85e96SFrançois Tigeot 		I915_WRITE(CHICKEN_PIPESL_1(params->crtc.pipe),
341c0e85e96SFrançois Tigeot 			   I915_READ(CHICKEN_PIPESL_1(params->crtc.pipe)) |
3422c9916cdSFrançois Tigeot 			   HSW_FBCQ_DIS);
3432c9916cdSFrançois Tigeot 	}
3442c9916cdSFrançois Tigeot 
345352ff8bdSFrançois Tigeot 	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
346352ff8bdSFrançois Tigeot 
347aee94f86SFrançois Tigeot 	intel_fbc_recompress(dev_priv);
3482c9916cdSFrançois Tigeot }
3492c9916cdSFrançois Tigeot 
350c0e85e96SFrançois Tigeot static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv)
351c0e85e96SFrançois Tigeot {
352c0e85e96SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 5)
353c0e85e96SFrançois Tigeot 		return ilk_fbc_is_active(dev_priv);
354c0e85e96SFrançois Tigeot 	else if (IS_GM45(dev_priv))
355c0e85e96SFrançois Tigeot 		return g4x_fbc_is_active(dev_priv);
356c0e85e96SFrançois Tigeot 	else
357c0e85e96SFrançois Tigeot 		return i8xx_fbc_is_active(dev_priv);
358c0e85e96SFrançois Tigeot }
359c0e85e96SFrançois Tigeot 
360c0e85e96SFrançois Tigeot static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv)
361c0e85e96SFrançois Tigeot {
362c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
363c0e85e96SFrançois Tigeot 
364c0e85e96SFrançois Tigeot 	fbc->active = true;
365c0e85e96SFrançois Tigeot 
366c0e85e96SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 7)
367c0e85e96SFrançois Tigeot 		gen7_fbc_activate(dev_priv);
368c0e85e96SFrançois Tigeot 	else if (INTEL_INFO(dev_priv)->gen >= 5)
369c0e85e96SFrançois Tigeot 		ilk_fbc_activate(dev_priv);
370c0e85e96SFrançois Tigeot 	else if (IS_GM45(dev_priv))
371c0e85e96SFrançois Tigeot 		g4x_fbc_activate(dev_priv);
372c0e85e96SFrançois Tigeot 	else
373c0e85e96SFrançois Tigeot 		i8xx_fbc_activate(dev_priv);
374c0e85e96SFrançois Tigeot }
375c0e85e96SFrançois Tigeot 
376c0e85e96SFrançois Tigeot static void intel_fbc_hw_deactivate(struct drm_i915_private *dev_priv)
377c0e85e96SFrançois Tigeot {
378c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
379c0e85e96SFrançois Tigeot 
380c0e85e96SFrançois Tigeot 	fbc->active = false;
381c0e85e96SFrançois Tigeot 
382c0e85e96SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 5)
383c0e85e96SFrançois Tigeot 		ilk_fbc_deactivate(dev_priv);
384c0e85e96SFrançois Tigeot 	else if (IS_GM45(dev_priv))
385c0e85e96SFrançois Tigeot 		g4x_fbc_deactivate(dev_priv);
386c0e85e96SFrançois Tigeot 	else
387c0e85e96SFrançois Tigeot 		i8xx_fbc_deactivate(dev_priv);
388c0e85e96SFrançois Tigeot }
389c0e85e96SFrançois Tigeot 
3902c9916cdSFrançois Tigeot /**
391aee94f86SFrançois Tigeot  * intel_fbc_is_active - Is FBC active?
392a05eeebfSFrançois Tigeot  * @dev_priv: i915 device instance
3932c9916cdSFrançois Tigeot  *
3942c9916cdSFrançois Tigeot  * This function is used to verify the current state of FBC.
3951487f786SFrançois Tigeot  *
3962c9916cdSFrançois Tigeot  * FIXME: This should be tracked in the plane config eventually
3972c9916cdSFrançois Tigeot  * instead of queried at runtime for most callers.
3982c9916cdSFrançois Tigeot  */
399aee94f86SFrançois Tigeot bool intel_fbc_is_active(struct drm_i915_private *dev_priv)
4002c9916cdSFrançois Tigeot {
401aee94f86SFrançois Tigeot 	return dev_priv->fbc.active;
4022c9916cdSFrançois Tigeot }
4032c9916cdSFrançois Tigeot 
4042c9916cdSFrançois Tigeot static void intel_fbc_work_fn(struct work_struct *__work)
4052c9916cdSFrançois Tigeot {
406aee94f86SFrançois Tigeot 	struct drm_i915_private *dev_priv =
407aee94f86SFrançois Tigeot 		container_of(__work, struct drm_i915_private, fbc.work.work);
408c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
409c0e85e96SFrançois Tigeot 	struct intel_fbc_work *work = &fbc->work;
410c0e85e96SFrançois Tigeot 	struct intel_crtc *crtc = fbc->crtc;
411303bf270SFrançois Tigeot 	struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[crtc->pipe];
412c0e85e96SFrançois Tigeot 
413c0e85e96SFrançois Tigeot 	if (drm_crtc_vblank_get(&crtc->base)) {
414c0e85e96SFrançois Tigeot 		DRM_ERROR("vblank not available for FBC on pipe %c\n",
415c0e85e96SFrançois Tigeot 			  pipe_name(crtc->pipe));
416c0e85e96SFrançois Tigeot 
417c0e85e96SFrançois Tigeot 		mutex_lock(&fbc->lock);
418c0e85e96SFrançois Tigeot 		work->scheduled = false;
419c0e85e96SFrançois Tigeot 		mutex_unlock(&fbc->lock);
420c0e85e96SFrançois Tigeot 		return;
421c0e85e96SFrançois Tigeot 	}
4222c9916cdSFrançois Tigeot 
423aee94f86SFrançois Tigeot retry:
4242c9916cdSFrançois Tigeot 	/* Delay the actual enabling to let pageflipping cease and the
4252c9916cdSFrançois Tigeot 	 * display to settle before starting the compression. Note that
4262c9916cdSFrançois Tigeot 	 * this delay also serves a second purpose: it allows for a
4272c9916cdSFrançois Tigeot 	 * vblank to pass after disabling the FBC before we attempt
4282c9916cdSFrançois Tigeot 	 * to modify the control registers.
4292c9916cdSFrançois Tigeot 	 *
4302c9916cdSFrançois Tigeot 	 * WaFbcWaitForVBlankBeforeEnable:ilk,snb
431c0e85e96SFrançois Tigeot 	 *
432c0e85e96SFrançois Tigeot 	 * It is also worth mentioning that since work->scheduled_vblank can be
433c0e85e96SFrançois Tigeot 	 * updated multiple times by the other threads, hitting the timeout is
434c0e85e96SFrançois Tigeot 	 * not an error condition. We'll just end up hitting the "goto retry"
435c0e85e96SFrançois Tigeot 	 * case below.
4362c9916cdSFrançois Tigeot 	 */
437c0e85e96SFrançois Tigeot 	wait_event_timeout(vblank->queue,
438c0e85e96SFrançois Tigeot 		drm_crtc_vblank_count(&crtc->base) != work->scheduled_vblank,
439c0e85e96SFrançois Tigeot 		msecs_to_jiffies(50));
440aee94f86SFrançois Tigeot 
441c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
442aee94f86SFrançois Tigeot 
443aee94f86SFrançois Tigeot 	/* Were we cancelled? */
444aee94f86SFrançois Tigeot 	if (!work->scheduled)
445aee94f86SFrançois Tigeot 		goto out;
446aee94f86SFrançois Tigeot 
447aee94f86SFrançois Tigeot 	/* Were we delayed again while this function was sleeping? */
448c0e85e96SFrançois Tigeot 	if (drm_crtc_vblank_count(&crtc->base) == work->scheduled_vblank) {
449c0e85e96SFrançois Tigeot 		mutex_unlock(&fbc->lock);
450aee94f86SFrançois Tigeot 		goto retry;
4512c9916cdSFrançois Tigeot 	}
4522c9916cdSFrançois Tigeot 
453c0e85e96SFrançois Tigeot 	intel_fbc_hw_activate(dev_priv);
454aee94f86SFrançois Tigeot 
455aee94f86SFrançois Tigeot 	work->scheduled = false;
456aee94f86SFrançois Tigeot 
457aee94f86SFrançois Tigeot out:
458c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
459c0e85e96SFrançois Tigeot 	drm_crtc_vblank_put(&crtc->base);
460aee94f86SFrançois Tigeot }
461aee94f86SFrançois Tigeot 
462aee94f86SFrançois Tigeot static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
463aee94f86SFrançois Tigeot {
464303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
465c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
466c0e85e96SFrançois Tigeot 	struct intel_fbc_work *work = &fbc->work;
467aee94f86SFrançois Tigeot 
468c0e85e96SFrançois Tigeot 	WARN_ON(!mutex_is_locked(&fbc->lock));
469aee94f86SFrançois Tigeot 
470c0e85e96SFrançois Tigeot 	if (drm_crtc_vblank_get(&crtc->base)) {
471c0e85e96SFrançois Tigeot 		DRM_ERROR("vblank not available for FBC on pipe %c\n",
472c0e85e96SFrançois Tigeot 			  pipe_name(crtc->pipe));
473c0e85e96SFrançois Tigeot 		return;
474c0e85e96SFrançois Tigeot 	}
475c0e85e96SFrançois Tigeot 
476c0e85e96SFrançois Tigeot 	/* It is useless to call intel_fbc_cancel_work() or cancel_work() in
477c0e85e96SFrançois Tigeot 	 * this function since we're not releasing fbc.lock, so it won't have an
478c0e85e96SFrançois Tigeot 	 * opportunity to grab it to discover that it was cancelled. So we just
479c0e85e96SFrançois Tigeot 	 * update the expected jiffy count. */
480aee94f86SFrançois Tigeot 	work->scheduled = true;
481c0e85e96SFrançois Tigeot 	work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base);
482c0e85e96SFrançois Tigeot 	drm_crtc_vblank_put(&crtc->base);
483aee94f86SFrançois Tigeot 
484aee94f86SFrançois Tigeot 	schedule_work(&work->work);
485aee94f86SFrançois Tigeot }
486aee94f86SFrançois Tigeot 
487c0e85e96SFrançois Tigeot static void intel_fbc_deactivate(struct drm_i915_private *dev_priv)
4882c9916cdSFrançois Tigeot {
489c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
4902c9916cdSFrançois Tigeot 
491c0e85e96SFrançois Tigeot 	WARN_ON(!mutex_is_locked(&fbc->lock));
4922c9916cdSFrançois Tigeot 
493c0e85e96SFrançois Tigeot 	/* Calling cancel_work() here won't help due to the fact that the work
494c0e85e96SFrançois Tigeot 	 * function grabs fbc->lock. Just set scheduled to false so the work
495c0e85e96SFrançois Tigeot 	 * function can know it was cancelled. */
496c0e85e96SFrançois Tigeot 	fbc->work.scheduled = false;
497c0e85e96SFrançois Tigeot 
498c0e85e96SFrançois Tigeot 	if (fbc->active)
499c0e85e96SFrançois Tigeot 		intel_fbc_hw_deactivate(dev_priv);
500a05eeebfSFrançois Tigeot }
501a05eeebfSFrançois Tigeot 
5021487f786SFrançois Tigeot static bool multiple_pipes_ok(struct intel_crtc *crtc,
5031487f786SFrançois Tigeot 			      struct intel_plane_state *plane_state)
504a05eeebfSFrançois Tigeot {
5051487f786SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
506c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
507c0e85e96SFrançois Tigeot 	enum i915_pipe pipe = crtc->pipe;
508a05eeebfSFrançois Tigeot 
509c0e85e96SFrançois Tigeot 	/* Don't even bother tracking anything we don't need. */
510c0e85e96SFrançois Tigeot 	if (!no_fbc_on_multiple_pipes(dev_priv))
511a05eeebfSFrançois Tigeot 		return true;
512a05eeebfSFrançois Tigeot 
513*1e12ee3bSFrançois Tigeot 	if (plane_state->base.visible)
514c0e85e96SFrançois Tigeot 		fbc->visible_pipes_mask |= (1 << pipe);
515c0e85e96SFrançois Tigeot 	else
516c0e85e96SFrançois Tigeot 		fbc->visible_pipes_mask &= ~(1 << pipe);
517a05eeebfSFrançois Tigeot 
518c0e85e96SFrançois Tigeot 	return (fbc->visible_pipes_mask & ~(1 << pipe)) != 0;
519a05eeebfSFrançois Tigeot }
520a05eeebfSFrançois Tigeot 
521a05eeebfSFrançois Tigeot static int find_compression_threshold(struct drm_i915_private *dev_priv,
522a05eeebfSFrançois Tigeot 				      struct drm_mm_node *node,
523a05eeebfSFrançois Tigeot 				      int size,
524a05eeebfSFrançois Tigeot 				      int fb_cpp)
525a05eeebfSFrançois Tigeot {
5268621f407SFrançois Tigeot 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
527a05eeebfSFrançois Tigeot 	int compression_threshold = 1;
528a05eeebfSFrançois Tigeot 	int ret;
529352ff8bdSFrançois Tigeot 	u64 end;
530352ff8bdSFrançois Tigeot 
531352ff8bdSFrançois Tigeot 	/* The FBC hardware for BDW/SKL doesn't have access to the stolen
532352ff8bdSFrançois Tigeot 	 * reserved range size, so it always assumes the maximum (8mb) is used.
533352ff8bdSFrançois Tigeot 	 * If we enable FBC using a CFB on that memory range we'll get FIFO
534352ff8bdSFrançois Tigeot 	 * underruns, even if that range is not reserved by the BIOS. */
535aee94f86SFrançois Tigeot 	if (IS_BROADWELL(dev_priv) ||
536aee94f86SFrançois Tigeot 	    IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
5378621f407SFrançois Tigeot 		end = ggtt->stolen_size - 8 * 1024 * 1024;
538352ff8bdSFrançois Tigeot 	else
5398621f407SFrançois Tigeot 		end = ggtt->stolen_usable_size;
540a05eeebfSFrançois Tigeot 
541a05eeebfSFrançois Tigeot 	/* HACK: This code depends on what we will do in *_enable_fbc. If that
542a05eeebfSFrançois Tigeot 	 * code changes, this code needs to change as well.
543a05eeebfSFrançois Tigeot 	 *
544a05eeebfSFrançois Tigeot 	 * The enable_fbc code will attempt to use one of our 2 compression
545a05eeebfSFrançois Tigeot 	 * thresholds, therefore, in that case, we only have 1 resort.
546a05eeebfSFrançois Tigeot 	 */
547a05eeebfSFrançois Tigeot 
548a05eeebfSFrançois Tigeot 	/* Try to over-allocate to reduce reallocations and fragmentation. */
549352ff8bdSFrançois Tigeot 	ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size <<= 1,
550352ff8bdSFrançois Tigeot 						   4096, 0, end);
551a05eeebfSFrançois Tigeot 	if (ret == 0)
552a05eeebfSFrançois Tigeot 		return compression_threshold;
553a05eeebfSFrançois Tigeot 
554a05eeebfSFrançois Tigeot again:
555a05eeebfSFrançois Tigeot 	/* HW's ability to limit the CFB is 1:4 */
556a05eeebfSFrançois Tigeot 	if (compression_threshold > 4 ||
557a05eeebfSFrançois Tigeot 	    (fb_cpp == 2 && compression_threshold == 2))
558a05eeebfSFrançois Tigeot 		return 0;
559a05eeebfSFrançois Tigeot 
560352ff8bdSFrançois Tigeot 	ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1,
561352ff8bdSFrançois Tigeot 						   4096, 0, end);
562a05eeebfSFrançois Tigeot 	if (ret && INTEL_INFO(dev_priv)->gen <= 4) {
563a05eeebfSFrançois Tigeot 		return 0;
564a05eeebfSFrançois Tigeot 	} else if (ret) {
565a05eeebfSFrançois Tigeot 		compression_threshold <<= 1;
566a05eeebfSFrançois Tigeot 		goto again;
567a05eeebfSFrançois Tigeot 	} else {
568a05eeebfSFrançois Tigeot 		return compression_threshold;
569a05eeebfSFrançois Tigeot 	}
570a05eeebfSFrançois Tigeot }
571a05eeebfSFrançois Tigeot 
572aee94f86SFrançois Tigeot static int intel_fbc_alloc_cfb(struct intel_crtc *crtc)
573a05eeebfSFrançois Tigeot {
574303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
575c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
576aee94f86SFrançois Tigeot 	struct drm_mm_node *compressed_llb = NULL;
577aee94f86SFrançois Tigeot 	int size, fb_cpp, ret;
578aee94f86SFrançois Tigeot 
579c0e85e96SFrançois Tigeot 	WARN_ON(drm_mm_node_allocated(&fbc->compressed_fb));
580aee94f86SFrançois Tigeot 
581c0e85e96SFrançois Tigeot 	size = intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache);
582c0e85e96SFrançois Tigeot 	fb_cpp = drm_format_plane_cpp(fbc->state_cache.fb.pixel_format, 0);
583a05eeebfSFrançois Tigeot 
584c0e85e96SFrançois Tigeot 	ret = find_compression_threshold(dev_priv, &fbc->compressed_fb,
585a05eeebfSFrançois Tigeot 					 size, fb_cpp);
586a05eeebfSFrançois Tigeot 	if (!ret)
587a05eeebfSFrançois Tigeot 		goto err_llb;
588a05eeebfSFrançois Tigeot 	else if (ret > 1) {
589a05eeebfSFranç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");
590a05eeebfSFrançois Tigeot 
591a05eeebfSFrançois Tigeot 	}
592a05eeebfSFrançois Tigeot 
593c0e85e96SFrançois Tigeot 	fbc->threshold = ret;
594a05eeebfSFrançois Tigeot 
595a05eeebfSFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 5)
596c0e85e96SFrançois Tigeot 		I915_WRITE(ILK_DPFC_CB_BASE, fbc->compressed_fb.start);
597a05eeebfSFrançois Tigeot 	else if (IS_GM45(dev_priv)) {
598c0e85e96SFrançois Tigeot 		I915_WRITE(DPFC_CB_BASE, fbc->compressed_fb.start);
599a05eeebfSFrançois Tigeot 	} else {
600a05eeebfSFrançois Tigeot 		compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL);
601a05eeebfSFrançois Tigeot 		if (!compressed_llb)
602a05eeebfSFrançois Tigeot 			goto err_fb;
603a05eeebfSFrançois Tigeot 
604a05eeebfSFrançois Tigeot 		ret = i915_gem_stolen_insert_node(dev_priv, compressed_llb,
605a05eeebfSFrançois Tigeot 						  4096, 4096);
606a05eeebfSFrançois Tigeot 		if (ret)
607a05eeebfSFrançois Tigeot 			goto err_fb;
608a05eeebfSFrançois Tigeot 
609c0e85e96SFrançois Tigeot 		fbc->compressed_llb = compressed_llb;
610a05eeebfSFrançois Tigeot 
611a05eeebfSFrançois Tigeot 		I915_WRITE(FBC_CFB_BASE,
612c0e85e96SFrançois Tigeot 			   dev_priv->mm.stolen_base + fbc->compressed_fb.start);
613a05eeebfSFrançois Tigeot 		I915_WRITE(FBC_LL_BASE,
614a05eeebfSFrançois Tigeot 			   dev_priv->mm.stolen_base + compressed_llb->start);
615a05eeebfSFrançois Tigeot 	}
616a05eeebfSFrançois Tigeot 
617f77dbd6cSFrançois Tigeot 	DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
618c0e85e96SFrançois Tigeot 		      fbc->compressed_fb.size, fbc->threshold);
619a05eeebfSFrançois Tigeot 
620a05eeebfSFrançois Tigeot 	return 0;
621a05eeebfSFrançois Tigeot 
622a05eeebfSFrançois Tigeot err_fb:
623a05eeebfSFrançois Tigeot 	kfree(compressed_llb);
624c0e85e96SFrançois Tigeot 	i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb);
625a05eeebfSFrançois Tigeot err_llb:
626a05eeebfSFranç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);
627a05eeebfSFrançois Tigeot 	return -ENOSPC;
628a05eeebfSFrançois Tigeot }
629a05eeebfSFrançois Tigeot 
630a05eeebfSFrançois Tigeot static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
631a05eeebfSFrançois Tigeot {
632c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
633a05eeebfSFrançois Tigeot 
634c0e85e96SFrançois Tigeot 	if (drm_mm_node_allocated(&fbc->compressed_fb))
635c0e85e96SFrançois Tigeot 		i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb);
636c0e85e96SFrançois Tigeot 
637c0e85e96SFrançois Tigeot 	if (fbc->compressed_llb) {
638c0e85e96SFrançois Tigeot 		i915_gem_stolen_remove_node(dev_priv, fbc->compressed_llb);
639c0e85e96SFrançois Tigeot 		kfree(fbc->compressed_llb);
640a05eeebfSFrançois Tigeot 	}
641a05eeebfSFrançois Tigeot }
642a05eeebfSFrançois Tigeot 
643a05eeebfSFrançois Tigeot void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
644a05eeebfSFrançois Tigeot {
645c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
646c0e85e96SFrançois Tigeot 
647352ff8bdSFrançois Tigeot 	if (!fbc_supported(dev_priv))
648a05eeebfSFrançois Tigeot 		return;
649a05eeebfSFrançois Tigeot 
650c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
651a05eeebfSFrançois Tigeot 	__intel_fbc_cleanup_cfb(dev_priv);
652c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
653a05eeebfSFrançois Tigeot }
654a05eeebfSFrançois Tigeot 
655352ff8bdSFrançois Tigeot static bool stride_is_valid(struct drm_i915_private *dev_priv,
656352ff8bdSFrançois Tigeot 			    unsigned int stride)
657352ff8bdSFrançois Tigeot {
658352ff8bdSFrançois Tigeot 	/* These should have been caught earlier. */
659352ff8bdSFrançois Tigeot 	WARN_ON(stride < 512);
660352ff8bdSFrançois Tigeot 	WARN_ON((stride & (64 - 1)) != 0);
661352ff8bdSFrançois Tigeot 
662352ff8bdSFrançois Tigeot 	/* Below are the additional FBC restrictions. */
663352ff8bdSFrançois Tigeot 
664352ff8bdSFrançois Tigeot 	if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv))
665352ff8bdSFrançois Tigeot 		return stride == 4096 || stride == 8192;
666352ff8bdSFrançois Tigeot 
667352ff8bdSFrançois Tigeot 	if (IS_GEN4(dev_priv) && !IS_G4X(dev_priv) && stride < 2048)
668352ff8bdSFrançois Tigeot 		return false;
669352ff8bdSFrançois Tigeot 
670352ff8bdSFrançois Tigeot 	if (stride > 16384)
671352ff8bdSFrançois Tigeot 		return false;
672352ff8bdSFrançois Tigeot 
673352ff8bdSFrançois Tigeot 	return true;
674352ff8bdSFrançois Tigeot }
675352ff8bdSFrançois Tigeot 
676c0e85e96SFrançois Tigeot static bool pixel_format_is_valid(struct drm_i915_private *dev_priv,
677c0e85e96SFrançois Tigeot 				  uint32_t pixel_format)
678352ff8bdSFrançois Tigeot {
679c0e85e96SFrançois Tigeot 	switch (pixel_format) {
680352ff8bdSFrançois Tigeot 	case DRM_FORMAT_XRGB8888:
681352ff8bdSFrançois Tigeot 	case DRM_FORMAT_XBGR8888:
682352ff8bdSFrançois Tigeot 		return true;
683352ff8bdSFrançois Tigeot 	case DRM_FORMAT_XRGB1555:
684352ff8bdSFrançois Tigeot 	case DRM_FORMAT_RGB565:
685352ff8bdSFrançois Tigeot 		/* 16bpp not supported on gen2 */
686c0e85e96SFrançois Tigeot 		if (IS_GEN2(dev_priv))
687352ff8bdSFrançois Tigeot 			return false;
688352ff8bdSFrançois Tigeot 		/* WaFbcOnly1to1Ratio:ctg */
689352ff8bdSFrançois Tigeot 		if (IS_G4X(dev_priv))
690352ff8bdSFrançois Tigeot 			return false;
691352ff8bdSFrançois Tigeot 		return true;
692352ff8bdSFrançois Tigeot 	default:
693352ff8bdSFrançois Tigeot 		return false;
694352ff8bdSFrançois Tigeot 	}
695352ff8bdSFrançois Tigeot }
696352ff8bdSFrançois Tigeot 
697352ff8bdSFrançois Tigeot /*
698352ff8bdSFrançois Tigeot  * For some reason, the hardware tracking starts looking at whatever we
699352ff8bdSFrançois Tigeot  * programmed as the display plane base address register. It does not look at
700352ff8bdSFrançois Tigeot  * the X and Y offset registers. That's why we look at the crtc->adjusted{x,y}
701352ff8bdSFrançois Tigeot  * variables instead of just looking at the pipe/plane size.
702352ff8bdSFrançois Tigeot  */
703352ff8bdSFrançois Tigeot static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
704352ff8bdSFrançois Tigeot {
705303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
706c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
707352ff8bdSFrançois Tigeot 	unsigned int effective_w, effective_h, max_w, max_h;
708352ff8bdSFrançois Tigeot 
709352ff8bdSFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
710352ff8bdSFrançois Tigeot 		max_w = 4096;
711352ff8bdSFrançois Tigeot 		max_h = 4096;
712352ff8bdSFrançois Tigeot 	} else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
713352ff8bdSFrançois Tigeot 		max_w = 4096;
714352ff8bdSFrançois Tigeot 		max_h = 2048;
715352ff8bdSFrançois Tigeot 	} else {
716352ff8bdSFrançois Tigeot 		max_w = 2048;
717352ff8bdSFrançois Tigeot 		max_h = 1536;
718352ff8bdSFrançois Tigeot 	}
719352ff8bdSFrançois Tigeot 
720c0e85e96SFrançois Tigeot 	intel_fbc_get_plane_source_size(&fbc->state_cache, &effective_w,
721c0e85e96SFrançois Tigeot 					&effective_h);
722352ff8bdSFrançois Tigeot 	effective_w += crtc->adjusted_x;
723352ff8bdSFrançois Tigeot 	effective_h += crtc->adjusted_y;
724352ff8bdSFrançois Tigeot 
725352ff8bdSFrançois Tigeot 	return effective_w <= max_w && effective_h <= max_h;
726a05eeebfSFrançois Tigeot }
727a05eeebfSFrançois Tigeot 
728*1e12ee3bSFrançois Tigeot /* XXX replace me when we have VMA tracking for intel_plane_state */
729*1e12ee3bSFrançois Tigeot static int get_fence_id(struct drm_framebuffer *fb)
730*1e12ee3bSFrançois Tigeot {
731*1e12ee3bSFrançois Tigeot 	struct i915_vma *vma = i915_gem_object_to_ggtt(intel_fb_obj(fb), NULL);
732*1e12ee3bSFrançois Tigeot 
733*1e12ee3bSFrançois Tigeot 	return vma && vma->fence ? vma->fence->id : I915_FENCE_REG_NONE;
734*1e12ee3bSFrançois Tigeot }
735*1e12ee3bSFrançois Tigeot 
7361487f786SFrançois Tigeot static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
7371487f786SFrançois Tigeot 					 struct intel_crtc_state *crtc_state,
7381487f786SFrançois Tigeot 					 struct intel_plane_state *plane_state)
7392c9916cdSFrançois Tigeot {
740303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
741c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
742c0e85e96SFrançois Tigeot 	struct intel_fbc_state_cache *cache = &fbc->state_cache;
743c0e85e96SFrançois Tigeot 	struct drm_framebuffer *fb = plane_state->base.fb;
7442c9916cdSFrançois Tigeot 	struct drm_i915_gem_object *obj;
7452c9916cdSFrançois Tigeot 
746c0e85e96SFrançois Tigeot 	cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
747c0e85e96SFrançois Tigeot 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
748c0e85e96SFrançois Tigeot 		cache->crtc.hsw_bdw_pixel_rate =
749c0e85e96SFrançois Tigeot 			ilk_pipe_pixel_rate(crtc_state);
7502c9916cdSFrançois Tigeot 
751c0e85e96SFrançois Tigeot 	cache->plane.rotation = plane_state->base.rotation;
752*1e12ee3bSFrançois Tigeot 	cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16;
753*1e12ee3bSFrançois Tigeot 	cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16;
754*1e12ee3bSFrançois Tigeot 	cache->plane.visible = plane_state->base.visible;
755c0e85e96SFrançois Tigeot 
756c0e85e96SFrançois Tigeot 	if (!cache->plane.visible)
757aee94f86SFrançois Tigeot 		return;
758aee94f86SFrançois Tigeot 
759c0e85e96SFrançois Tigeot 	obj = intel_fb_obj(fb);
760c0e85e96SFrançois Tigeot 
761c0e85e96SFrançois Tigeot 	/* FIXME: We lack the proper locking here, so only run this on the
762c0e85e96SFrançois Tigeot 	 * platforms that need. */
7631487f786SFrançois Tigeot 	if (IS_GEN(dev_priv, 5, 6))
764*1e12ee3bSFrançois Tigeot 		cache->fb.ilk_ggtt_offset = i915_gem_object_ggtt_offset(obj, NULL);
765c0e85e96SFrançois Tigeot 	cache->fb.pixel_format = fb->pixel_format;
766c0e85e96SFrançois Tigeot 	cache->fb.stride = fb->pitches[0];
767*1e12ee3bSFrançois Tigeot 	cache->fb.fence_reg = get_fence_id(fb);
76871f41f3eSFrançois Tigeot 	cache->fb.tiling_mode = i915_gem_object_get_tiling(obj);
769aee94f86SFrançois Tigeot }
770aee94f86SFrançois Tigeot 
771c0e85e96SFrançois Tigeot static bool intel_fbc_can_activate(struct intel_crtc *crtc)
772c0e85e96SFrançois Tigeot {
773303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
774c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
775c0e85e96SFrançois Tigeot 	struct intel_fbc_state_cache *cache = &fbc->state_cache;
7762c9916cdSFrançois Tigeot 
777*1e12ee3bSFrançois Tigeot 	/* We don't need to use a state cache here since this information is
778*1e12ee3bSFrançois Tigeot 	 * global for all CRTC.
779*1e12ee3bSFrançois Tigeot 	 */
780*1e12ee3bSFrançois Tigeot 	if (fbc->underrun_detected) {
781*1e12ee3bSFrançois Tigeot 		fbc->no_fbc_reason = "underrun detected";
782*1e12ee3bSFrançois Tigeot 		return false;
783*1e12ee3bSFrançois Tigeot 	}
784*1e12ee3bSFrançois Tigeot 
785c0e85e96SFrançois Tigeot 	if (!cache->plane.visible) {
786c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "primary plane not visible";
787c0e85e96SFrançois Tigeot 		return false;
788c0e85e96SFrançois Tigeot 	}
789c0e85e96SFrançois Tigeot 
790c0e85e96SFrançois Tigeot 	if ((cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) ||
791c0e85e96SFrançois Tigeot 	    (cache->crtc.mode_flags & DRM_MODE_FLAG_DBLSCAN)) {
792c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "incompatible mode";
793c0e85e96SFrançois Tigeot 		return false;
7942c9916cdSFrançois Tigeot 	}
7952c9916cdSFrançois Tigeot 
796aee94f86SFrançois Tigeot 	if (!intel_fbc_hw_tracking_covers_screen(crtc)) {
797c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "mode too large for compression";
798c0e85e96SFrançois Tigeot 		return false;
7992c9916cdSFrançois Tigeot 	}
8002c9916cdSFrançois Tigeot 
8012c9916cdSFrançois Tigeot 	/* The use of a CPU fence is mandatory in order to detect writes
8022c9916cdSFrançois Tigeot 	 * by the CPU to the scanout and trigger updates to the FBC.
803*1e12ee3bSFrançois Tigeot 	 *
804*1e12ee3bSFrançois Tigeot 	 * Note that is possible for a tiled surface to be unmappable (and
805*1e12ee3bSFrançois Tigeot 	 * so have no fence associated with it) due to aperture constaints
806*1e12ee3bSFrançois Tigeot 	 * at the time of pinning.
8072c9916cdSFrançois Tigeot 	 */
808c0e85e96SFrançois Tigeot 	if (cache->fb.tiling_mode != I915_TILING_X ||
809c0e85e96SFrançois Tigeot 	    cache->fb.fence_reg == I915_FENCE_REG_NONE) {
810c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "framebuffer not tiled or fenced";
811c0e85e96SFrançois Tigeot 		return false;
8122c9916cdSFrançois Tigeot 	}
813a05eeebfSFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
8141dedbd3bSFrançois Tigeot 	    cache->plane.rotation != DRM_ROTATE_0) {
815c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "rotation unsupported";
816c0e85e96SFrançois Tigeot 		return false;
8172c9916cdSFrançois Tigeot 	}
8182c9916cdSFrançois Tigeot 
819c0e85e96SFrançois Tigeot 	if (!stride_is_valid(dev_priv, cache->fb.stride)) {
820c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "framebuffer stride not supported";
821c0e85e96SFrançois Tigeot 		return false;
822352ff8bdSFrançois Tigeot 	}
823352ff8bdSFrançois Tigeot 
824c0e85e96SFrançois Tigeot 	if (!pixel_format_is_valid(dev_priv, cache->fb.pixel_format)) {
825c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "pixel format is invalid";
826c0e85e96SFrançois Tigeot 		return false;
827352ff8bdSFrançois Tigeot 	}
828352ff8bdSFrançois Tigeot 
829352ff8bdSFrançois Tigeot 	/* WaFbcExceedCdClockThreshold:hsw,bdw */
830352ff8bdSFrançois Tigeot 	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
831c0e85e96SFrançois Tigeot 	    cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) {
832c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "pixel rate is too big";
833c0e85e96SFrançois Tigeot 		return false;
834352ff8bdSFrançois Tigeot 	}
835352ff8bdSFrançois Tigeot 
836aee94f86SFrançois Tigeot 	/* It is possible for the required CFB size change without a
837aee94f86SFrançois Tigeot 	 * crtc->disable + crtc->enable since it is possible to change the
838aee94f86SFrançois Tigeot 	 * stride without triggering a full modeset. Since we try to
839aee94f86SFrançois Tigeot 	 * over-allocate the CFB, there's a chance we may keep FBC enabled even
840aee94f86SFrançois Tigeot 	 * if this happens, but if we exceed the current CFB size we'll have to
841aee94f86SFrançois Tigeot 	 * disable FBC. Notice that it would be possible to disable FBC, wait
842aee94f86SFrançois Tigeot 	 * for a frame, free the stolen node, then try to reenable FBC in case
843aee94f86SFrançois Tigeot 	 * we didn't get any invalidate/deactivate calls, but this would require
844aee94f86SFrançois Tigeot 	 * a lot of tracking just for a specific case. If we conclude it's an
845aee94f86SFrançois Tigeot 	 * important case, we can implement it later. */
846c0e85e96SFrançois Tigeot 	if (intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) >
847c0e85e96SFrançois Tigeot 	    fbc->compressed_fb.size * fbc->threshold) {
848c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "CFB requirements changed";
849c0e85e96SFrançois Tigeot 		return false;
8502c9916cdSFrançois Tigeot 	}
8512c9916cdSFrançois Tigeot 
852c0e85e96SFrançois Tigeot 	return true;
853c0e85e96SFrançois Tigeot }
854c0e85e96SFrançois Tigeot 
855c0e85e96SFrançois Tigeot static bool intel_fbc_can_choose(struct intel_crtc *crtc)
856c0e85e96SFrançois Tigeot {
857303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
858c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
859c0e85e96SFrançois Tigeot 
8601487f786SFrançois Tigeot 	if (intel_vgpu_active(dev_priv)) {
861c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "VGPU is active";
862c0e85e96SFrançois Tigeot 		return false;
863c0e85e96SFrançois Tigeot 	}
864c0e85e96SFrançois Tigeot 
865c0e85e96SFrançois Tigeot 	if (!i915.enable_fbc) {
866303bf270SFrançois Tigeot 		fbc->no_fbc_reason = "disabled per module param or by default";
867c0e85e96SFrançois Tigeot 		return false;
868c0e85e96SFrançois Tigeot 	}
869c0e85e96SFrançois Tigeot 
870*1e12ee3bSFrançois Tigeot 	if (fbc->underrun_detected) {
871*1e12ee3bSFrançois Tigeot 		fbc->no_fbc_reason = "underrun detected";
872*1e12ee3bSFrançois Tigeot 		return false;
873*1e12ee3bSFrançois Tigeot 	}
874*1e12ee3bSFrançois Tigeot 
875c0e85e96SFrançois Tigeot 	if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) {
876c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "no enabled pipes can have FBC";
877c0e85e96SFrançois Tigeot 		return false;
878c0e85e96SFrançois Tigeot 	}
879c0e85e96SFrançois Tigeot 
880c0e85e96SFrançois Tigeot 	if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) {
881c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "no enabled planes can have FBC";
882c0e85e96SFrançois Tigeot 		return false;
883c0e85e96SFrançois Tigeot 	}
884c0e85e96SFrançois Tigeot 
885c0e85e96SFrançois Tigeot 	return true;
886c0e85e96SFrançois Tigeot }
887c0e85e96SFrançois Tigeot 
888c0e85e96SFrançois Tigeot static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
889c0e85e96SFrançois Tigeot 				     struct intel_fbc_reg_params *params)
890c0e85e96SFrançois Tigeot {
891303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
892c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
893c0e85e96SFrançois Tigeot 	struct intel_fbc_state_cache *cache = &fbc->state_cache;
894c0e85e96SFrançois Tigeot 
895c0e85e96SFrançois Tigeot 	/* Since all our fields are integer types, use memset here so the
896c0e85e96SFrançois Tigeot 	 * comparison function can rely on memcmp because the padding will be
897c0e85e96SFrançois Tigeot 	 * zero. */
898c0e85e96SFrançois Tigeot 	memset(params, 0, sizeof(*params));
899c0e85e96SFrançois Tigeot 
900c0e85e96SFrançois Tigeot 	params->crtc.pipe = crtc->pipe;
901c0e85e96SFrançois Tigeot 	params->crtc.plane = crtc->plane;
902c0e85e96SFrançois Tigeot 	params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc);
903c0e85e96SFrançois Tigeot 
904c0e85e96SFrançois Tigeot 	params->fb.pixel_format = cache->fb.pixel_format;
905c0e85e96SFrançois Tigeot 	params->fb.stride = cache->fb.stride;
906c0e85e96SFrançois Tigeot 	params->fb.fence_reg = cache->fb.fence_reg;
907c0e85e96SFrançois Tigeot 
908c0e85e96SFrançois Tigeot 	params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
909c0e85e96SFrançois Tigeot 
910c0e85e96SFrançois Tigeot 	params->fb.ggtt_offset = cache->fb.ilk_ggtt_offset;
911c0e85e96SFrançois Tigeot }
912c0e85e96SFrançois Tigeot 
913c0e85e96SFrançois Tigeot static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
914c0e85e96SFrançois Tigeot 				       struct intel_fbc_reg_params *params2)
915c0e85e96SFrançois Tigeot {
916c0e85e96SFrançois Tigeot 	/* We can use this since intel_fbc_get_reg_params() does a memset. */
917c0e85e96SFrançois Tigeot 	return memcmp(params1, params2, sizeof(*params1)) == 0;
918c0e85e96SFrançois Tigeot }
919c0e85e96SFrançois Tigeot 
9201487f786SFrançois Tigeot void intel_fbc_pre_update(struct intel_crtc *crtc,
9211487f786SFrançois Tigeot 			  struct intel_crtc_state *crtc_state,
9221487f786SFrançois Tigeot 			  struct intel_plane_state *plane_state)
923c0e85e96SFrançois Tigeot {
924303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
925c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
926c0e85e96SFrançois Tigeot 
927c0e85e96SFrançois Tigeot 	if (!fbc_supported(dev_priv))
928c0e85e96SFrançois Tigeot 		return;
929c0e85e96SFrançois Tigeot 
930c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
931c0e85e96SFrançois Tigeot 
9321487f786SFrançois Tigeot 	if (!multiple_pipes_ok(crtc, plane_state)) {
933c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "more than one pipe active";
934c0e85e96SFrançois Tigeot 		goto deactivate;
935c0e85e96SFrançois Tigeot 	}
936c0e85e96SFrançois Tigeot 
937c0e85e96SFrançois Tigeot 	if (!fbc->enabled || fbc->crtc != crtc)
938c0e85e96SFrançois Tigeot 		goto unlock;
939c0e85e96SFrançois Tigeot 
9401487f786SFrançois Tigeot 	intel_fbc_update_state_cache(crtc, crtc_state, plane_state);
941c0e85e96SFrançois Tigeot 
942c0e85e96SFrançois Tigeot deactivate:
943c0e85e96SFrançois Tigeot 	intel_fbc_deactivate(dev_priv);
944c0e85e96SFrançois Tigeot unlock:
945c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
946c0e85e96SFrançois Tigeot }
947c0e85e96SFrançois Tigeot 
948c0e85e96SFrançois Tigeot static void __intel_fbc_post_update(struct intel_crtc *crtc)
949c0e85e96SFrançois Tigeot {
950303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
951c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
952c0e85e96SFrançois Tigeot 	struct intel_fbc_reg_params old_params;
953c0e85e96SFrançois Tigeot 
954c0e85e96SFrançois Tigeot 	WARN_ON(!mutex_is_locked(&fbc->lock));
955c0e85e96SFrançois Tigeot 
956c0e85e96SFrançois Tigeot 	if (!fbc->enabled || fbc->crtc != crtc)
957c0e85e96SFrançois Tigeot 		return;
958c0e85e96SFrançois Tigeot 
959c0e85e96SFrançois Tigeot 	if (!intel_fbc_can_activate(crtc)) {
960c0e85e96SFrançois Tigeot 		WARN_ON(fbc->active);
961c0e85e96SFrançois Tigeot 		return;
962c0e85e96SFrançois Tigeot 	}
963c0e85e96SFrançois Tigeot 
964c0e85e96SFrançois Tigeot 	old_params = fbc->params;
965c0e85e96SFrançois Tigeot 	intel_fbc_get_reg_params(crtc, &fbc->params);
966c0e85e96SFrançois Tigeot 
9672c9916cdSFrançois Tigeot 	/* If the scanout has not changed, don't modify the FBC settings.
9682c9916cdSFrançois Tigeot 	 * Note that we make the fundamental assumption that the fb->obj
9692c9916cdSFrançois Tigeot 	 * cannot be unpinned (and have its GTT offset and fence revoked)
9702c9916cdSFrançois Tigeot 	 * without first being decoupled from the scanout and FBC disabled.
9712c9916cdSFrançois Tigeot 	 */
972c0e85e96SFrançois Tigeot 	if (fbc->active &&
973c0e85e96SFrançois Tigeot 	    intel_fbc_reg_params_equal(&old_params, &fbc->params))
9742c9916cdSFrançois Tigeot 		return;
9752c9916cdSFrançois Tigeot 
976c0e85e96SFrançois Tigeot 	intel_fbc_deactivate(dev_priv);
977aee94f86SFrançois Tigeot 	intel_fbc_schedule_activation(crtc);
978c0e85e96SFrançois Tigeot 	fbc->no_fbc_reason = "FBC enabled (active or scheduled)";
979a05eeebfSFrançois Tigeot }
980a05eeebfSFrançois Tigeot 
981c0e85e96SFrançois Tigeot void intel_fbc_post_update(struct intel_crtc *crtc)
982a05eeebfSFrançois Tigeot {
983303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
984c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
985aee94f86SFrançois Tigeot 
986352ff8bdSFrançois Tigeot 	if (!fbc_supported(dev_priv))
987a05eeebfSFrançois Tigeot 		return;
988a05eeebfSFrançois Tigeot 
989c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
990c0e85e96SFrançois Tigeot 	__intel_fbc_post_update(crtc);
991c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
992c0e85e96SFrançois Tigeot }
993c0e85e96SFrançois Tigeot 
994c0e85e96SFrançois Tigeot static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc)
995c0e85e96SFrançois Tigeot {
996c0e85e96SFrançois Tigeot 	if (fbc->enabled)
997c0e85e96SFrançois Tigeot 		return to_intel_plane(fbc->crtc->base.primary)->frontbuffer_bit;
998c0e85e96SFrançois Tigeot 	else
999c0e85e96SFrançois Tigeot 		return fbc->possible_framebuffer_bits;
10002c9916cdSFrançois Tigeot }
10012c9916cdSFrançois Tigeot 
1002477eb7f9SFrançois Tigeot void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
1003477eb7f9SFrançois Tigeot 			  unsigned int frontbuffer_bits,
1004477eb7f9SFrançois Tigeot 			  enum fb_op_origin origin)
1005477eb7f9SFrançois Tigeot {
1006c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1007477eb7f9SFrançois Tigeot 
1008352ff8bdSFrançois Tigeot 	if (!fbc_supported(dev_priv))
1009a05eeebfSFrançois Tigeot 		return;
1010a05eeebfSFrançois Tigeot 
1011c0e85e96SFrançois Tigeot 	if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP)
1012477eb7f9SFrançois Tigeot 		return;
1013477eb7f9SFrançois Tigeot 
1014c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1015a05eeebfSFrançois Tigeot 
1016c0e85e96SFrançois Tigeot 	fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits;
1017477eb7f9SFrançois Tigeot 
1018c0e85e96SFrançois Tigeot 	if (fbc->enabled && fbc->busy_bits)
1019c0e85e96SFrançois Tigeot 		intel_fbc_deactivate(dev_priv);
1020477eb7f9SFrançois Tigeot 
1021c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1022477eb7f9SFrançois Tigeot }
1023477eb7f9SFrançois Tigeot 
1024477eb7f9SFrançois Tigeot void intel_fbc_flush(struct drm_i915_private *dev_priv,
1025a05eeebfSFrançois Tigeot 		     unsigned int frontbuffer_bits, enum fb_op_origin origin)
1026477eb7f9SFrançois Tigeot {
1027c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1028c0e85e96SFrançois Tigeot 
1029352ff8bdSFrançois Tigeot 	if (!fbc_supported(dev_priv))
1030477eb7f9SFrançois Tigeot 		return;
1031477eb7f9SFrançois Tigeot 
1032c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1033a05eeebfSFrançois Tigeot 
1034c0e85e96SFrançois Tigeot 	fbc->busy_bits &= ~frontbuffer_bits;
1035477eb7f9SFrançois Tigeot 
10361487f786SFrançois Tigeot 	if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP)
10371487f786SFrançois Tigeot 		goto out;
10381487f786SFrançois Tigeot 
1039c0e85e96SFrançois Tigeot 	if (!fbc->busy_bits && fbc->enabled &&
1040c0e85e96SFrançois Tigeot 	    (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) {
1041c0e85e96SFrançois Tigeot 		if (fbc->active)
1042aee94f86SFrançois Tigeot 			intel_fbc_recompress(dev_priv);
1043c0e85e96SFrançois Tigeot 		else
1044c0e85e96SFrançois Tigeot 			__intel_fbc_post_update(fbc->crtc);
1045c0e85e96SFrançois Tigeot 	}
1046c0e85e96SFrançois Tigeot 
10471487f786SFrançois Tigeot out:
1048c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1049c0e85e96SFrançois Tigeot }
1050c0e85e96SFrançois Tigeot 
1051c0e85e96SFrançois Tigeot /**
1052c0e85e96SFrançois Tigeot  * intel_fbc_choose_crtc - select a CRTC to enable FBC on
1053c0e85e96SFrançois Tigeot  * @dev_priv: i915 device instance
1054c0e85e96SFrançois Tigeot  * @state: the atomic state structure
1055c0e85e96SFrançois Tigeot  *
1056c0e85e96SFrançois Tigeot  * This function looks at the proposed state for CRTCs and planes, then chooses
1057c0e85e96SFrançois Tigeot  * which pipe is going to have FBC by setting intel_crtc_state->enable_fbc to
1058c0e85e96SFrançois Tigeot  * true.
1059c0e85e96SFrançois Tigeot  *
1060c0e85e96SFrançois Tigeot  * Later, intel_fbc_enable is going to look for state->enable_fbc and then maybe
1061c0e85e96SFrançois Tigeot  * enable FBC for the chosen CRTC. If it does, it will set dev_priv->fbc.crtc.
1062c0e85e96SFrançois Tigeot  */
1063c0e85e96SFrançois Tigeot void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv,
1064c0e85e96SFrançois Tigeot 			   struct drm_atomic_state *state)
1065c0e85e96SFrançois Tigeot {
1066c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1067c0e85e96SFrançois Tigeot 	struct drm_crtc *crtc;
1068c0e85e96SFrançois Tigeot 	struct drm_crtc_state *crtc_state;
1069c0e85e96SFrançois Tigeot 	struct drm_plane *plane;
1070c0e85e96SFrançois Tigeot 	struct drm_plane_state *plane_state;
1071c0e85e96SFrançois Tigeot 	bool fbc_crtc_present = false;
1072c0e85e96SFrançois Tigeot 	int i, j;
1073c0e85e96SFrançois Tigeot 
1074c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1075c0e85e96SFrançois Tigeot 
1076c0e85e96SFrançois Tigeot 	for_each_crtc_in_state(state, crtc, crtc_state, i) {
1077c0e85e96SFrançois Tigeot 		if (fbc->crtc == to_intel_crtc(crtc)) {
1078c0e85e96SFrançois Tigeot 			fbc_crtc_present = true;
1079c0e85e96SFrançois Tigeot 			break;
1080c0e85e96SFrançois Tigeot 		}
1081c0e85e96SFrançois Tigeot 	}
1082c0e85e96SFrançois Tigeot 	/* This atomic commit doesn't involve the CRTC currently tied to FBC. */
1083c0e85e96SFrançois Tigeot 	if (!fbc_crtc_present && fbc->crtc != NULL)
1084c0e85e96SFrançois Tigeot 		goto out;
1085c0e85e96SFrançois Tigeot 
1086c0e85e96SFrançois Tigeot 	/* Simply choose the first CRTC that is compatible and has a visible
1087c0e85e96SFrançois Tigeot 	 * plane. We could go for fancier schemes such as checking the plane
1088c0e85e96SFrançois Tigeot 	 * size, but this would just affect the few platforms that don't tie FBC
1089c0e85e96SFrançois Tigeot 	 * to pipe or plane A. */
1090c0e85e96SFrançois Tigeot 	for_each_plane_in_state(state, plane, plane_state, i) {
1091c0e85e96SFrançois Tigeot 		struct intel_plane_state *intel_plane_state =
1092c0e85e96SFrançois Tigeot 			to_intel_plane_state(plane_state);
1093c0e85e96SFrançois Tigeot 
1094*1e12ee3bSFrançois Tigeot 		if (!intel_plane_state->base.visible)
1095c0e85e96SFrançois Tigeot 			continue;
1096c0e85e96SFrançois Tigeot 
1097c0e85e96SFrançois Tigeot 		for_each_crtc_in_state(state, crtc, crtc_state, j) {
1098c0e85e96SFrançois Tigeot 			struct intel_crtc_state *intel_crtc_state =
1099c0e85e96SFrançois Tigeot 				to_intel_crtc_state(crtc_state);
1100c0e85e96SFrançois Tigeot 
1101c0e85e96SFrançois Tigeot 			if (plane_state->crtc != crtc)
1102c0e85e96SFrançois Tigeot 				continue;
1103c0e85e96SFrançois Tigeot 
1104c0e85e96SFrançois Tigeot 			if (!intel_fbc_can_choose(to_intel_crtc(crtc)))
1105c0e85e96SFrançois Tigeot 				break;
1106c0e85e96SFrançois Tigeot 
1107c0e85e96SFrançois Tigeot 			intel_crtc_state->enable_fbc = true;
1108c0e85e96SFrançois Tigeot 			goto out;
1109aee94f86SFrançois Tigeot 		}
1110a05eeebfSFrançois Tigeot 	}
1111a05eeebfSFrançois Tigeot 
1112c0e85e96SFrançois Tigeot out:
1113c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1114477eb7f9SFrançois Tigeot }
1115477eb7f9SFrançois Tigeot 
11162c9916cdSFrançois Tigeot /**
1117aee94f86SFrançois Tigeot  * intel_fbc_enable: tries to enable FBC on the CRTC
1118aee94f86SFrançois Tigeot  * @crtc: the CRTC
111987df8fc6SFrançois Tigeot  * @crtc_state: corresponding &drm_crtc_state for @crtc
112087df8fc6SFrançois Tigeot  * @plane_state: corresponding &drm_plane_state for the primary plane of @crtc
1121aee94f86SFrançois Tigeot  *
1122c0e85e96SFrançois Tigeot  * This function checks if the given CRTC was chosen for FBC, then enables it if
1123c0e85e96SFrançois Tigeot  * possible. Notice that it doesn't activate FBC. It is valid to call
1124c0e85e96SFrançois Tigeot  * intel_fbc_enable multiple times for the same pipe without an
1125c0e85e96SFrançois Tigeot  * intel_fbc_disable in the middle, as long as it is deactivated.
1126aee94f86SFrançois Tigeot  */
11271487f786SFrançois Tigeot void intel_fbc_enable(struct intel_crtc *crtc,
11281487f786SFrançois Tigeot 		      struct intel_crtc_state *crtc_state,
11291487f786SFrançois Tigeot 		      struct intel_plane_state *plane_state)
1130aee94f86SFrançois Tigeot {
1131303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1132c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1133aee94f86SFrançois Tigeot 
1134aee94f86SFrançois Tigeot 	if (!fbc_supported(dev_priv))
1135aee94f86SFrançois Tigeot 		return;
1136aee94f86SFrançois Tigeot 
1137c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1138aee94f86SFrançois Tigeot 
1139c0e85e96SFrançois Tigeot 	if (fbc->enabled) {
1140c0e85e96SFrançois Tigeot 		WARN_ON(fbc->crtc == NULL);
1141c0e85e96SFrançois Tigeot 		if (fbc->crtc == crtc) {
11421487f786SFrançois Tigeot 			WARN_ON(!crtc_state->enable_fbc);
1143c0e85e96SFrançois Tigeot 			WARN_ON(fbc->active);
1144c0e85e96SFrançois Tigeot 		}
1145aee94f86SFrançois Tigeot 		goto out;
1146aee94f86SFrançois Tigeot 	}
1147aee94f86SFrançois Tigeot 
11481487f786SFrançois Tigeot 	if (!crtc_state->enable_fbc)
1149aee94f86SFrançois Tigeot 		goto out;
1150aee94f86SFrançois Tigeot 
1151c0e85e96SFrançois Tigeot 	WARN_ON(fbc->active);
1152c0e85e96SFrançois Tigeot 	WARN_ON(fbc->crtc != NULL);
1153aee94f86SFrançois Tigeot 
11541487f786SFrançois Tigeot 	intel_fbc_update_state_cache(crtc, crtc_state, plane_state);
1155aee94f86SFrançois Tigeot 	if (intel_fbc_alloc_cfb(crtc)) {
1156c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "not enough stolen memory";
1157aee94f86SFrançois Tigeot 		goto out;
1158aee94f86SFrançois Tigeot 	}
1159aee94f86SFrançois Tigeot 
1160aee94f86SFrançois Tigeot 	DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe));
1161c0e85e96SFrançois Tigeot 	fbc->no_fbc_reason = "FBC enabled but not active yet\n";
1162aee94f86SFrançois Tigeot 
1163c0e85e96SFrançois Tigeot 	fbc->enabled = true;
1164c0e85e96SFrançois Tigeot 	fbc->crtc = crtc;
1165aee94f86SFrançois Tigeot out:
1166c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1167aee94f86SFrançois Tigeot }
1168aee94f86SFrançois Tigeot 
1169aee94f86SFrançois Tigeot /**
1170aee94f86SFrançois Tigeot  * __intel_fbc_disable - disable FBC
1171aee94f86SFrançois Tigeot  * @dev_priv: i915 device instance
1172aee94f86SFrançois Tigeot  *
1173aee94f86SFrançois Tigeot  * This is the low level function that actually disables FBC. Callers should
1174aee94f86SFrançois Tigeot  * grab the FBC lock.
1175aee94f86SFrançois Tigeot  */
1176aee94f86SFrançois Tigeot static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
1177aee94f86SFrançois Tigeot {
1178c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1179c0e85e96SFrançois Tigeot 	struct intel_crtc *crtc = fbc->crtc;
1180aee94f86SFrançois Tigeot 
1181c0e85e96SFrançois Tigeot 	WARN_ON(!mutex_is_locked(&fbc->lock));
1182c0e85e96SFrançois Tigeot 	WARN_ON(!fbc->enabled);
1183c0e85e96SFrançois Tigeot 	WARN_ON(fbc->active);
1184c0e85e96SFrançois Tigeot 	WARN_ON(crtc->active);
1185aee94f86SFrançois Tigeot 
1186aee94f86SFrançois Tigeot 	DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe));
1187aee94f86SFrançois Tigeot 
1188aee94f86SFrançois Tigeot 	__intel_fbc_cleanup_cfb(dev_priv);
1189aee94f86SFrançois Tigeot 
1190c0e85e96SFrançois Tigeot 	fbc->enabled = false;
1191c0e85e96SFrançois Tigeot 	fbc->crtc = NULL;
1192aee94f86SFrançois Tigeot }
1193aee94f86SFrançois Tigeot 
1194aee94f86SFrançois Tigeot /**
1195c0e85e96SFrançois Tigeot  * intel_fbc_disable - disable FBC if it's associated with crtc
1196aee94f86SFrançois Tigeot  * @crtc: the CRTC
1197aee94f86SFrançois Tigeot  *
1198aee94f86SFrançois Tigeot  * This function disables FBC if it's associated with the provided CRTC.
1199aee94f86SFrançois Tigeot  */
1200c0e85e96SFrançois Tigeot void intel_fbc_disable(struct intel_crtc *crtc)
1201aee94f86SFrançois Tigeot {
1202303bf270SFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1203c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1204aee94f86SFrançois Tigeot 
1205aee94f86SFrançois Tigeot 	if (!fbc_supported(dev_priv))
1206aee94f86SFrançois Tigeot 		return;
1207aee94f86SFrançois Tigeot 
1208c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
120971f41f3eSFrançois Tigeot 	if (fbc->crtc == crtc)
1210aee94f86SFrançois Tigeot 		__intel_fbc_disable(dev_priv);
1211c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1212c0e85e96SFrançois Tigeot 
1213c0e85e96SFrançois Tigeot 	cancel_work_sync(&fbc->work.work);
1214aee94f86SFrançois Tigeot }
1215aee94f86SFrançois Tigeot 
1216aee94f86SFrançois Tigeot /**
1217c0e85e96SFrançois Tigeot  * intel_fbc_global_disable - globally disable FBC
1218aee94f86SFrançois Tigeot  * @dev_priv: i915 device instance
1219aee94f86SFrançois Tigeot  *
1220aee94f86SFrançois Tigeot  * This function disables FBC regardless of which CRTC is associated with it.
1221aee94f86SFrançois Tigeot  */
1222c0e85e96SFrançois Tigeot void intel_fbc_global_disable(struct drm_i915_private *dev_priv)
1223aee94f86SFrançois Tigeot {
1224c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1225c0e85e96SFrançois Tigeot 
1226aee94f86SFrançois Tigeot 	if (!fbc_supported(dev_priv))
1227aee94f86SFrançois Tigeot 		return;
1228aee94f86SFrançois Tigeot 
1229c0e85e96SFrançois Tigeot 	mutex_lock(&fbc->lock);
1230c0e85e96SFrançois Tigeot 	if (fbc->enabled)
1231aee94f86SFrançois Tigeot 		__intel_fbc_disable(dev_priv);
1232c0e85e96SFrançois Tigeot 	mutex_unlock(&fbc->lock);
1233c0e85e96SFrançois Tigeot 
1234c0e85e96SFrançois Tigeot 	cancel_work_sync(&fbc->work.work);
1235c0e85e96SFrançois Tigeot }
1236c0e85e96SFrançois Tigeot 
1237*1e12ee3bSFrançois Tigeot static void intel_fbc_underrun_work_fn(struct work_struct *work)
1238*1e12ee3bSFrançois Tigeot {
1239*1e12ee3bSFrançois Tigeot 	struct drm_i915_private *dev_priv =
1240*1e12ee3bSFrançois Tigeot 		container_of(work, struct drm_i915_private, fbc.underrun_work);
1241*1e12ee3bSFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1242*1e12ee3bSFrançois Tigeot 
1243*1e12ee3bSFrançois Tigeot 	mutex_lock(&fbc->lock);
1244*1e12ee3bSFrançois Tigeot 
1245*1e12ee3bSFrançois Tigeot 	/* Maybe we were scheduled twice. */
1246*1e12ee3bSFrançois Tigeot 	if (fbc->underrun_detected)
1247*1e12ee3bSFrançois Tigeot 		goto out;
1248*1e12ee3bSFrançois Tigeot 
1249*1e12ee3bSFrançois Tigeot 	DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n");
1250*1e12ee3bSFrançois Tigeot 	fbc->underrun_detected = true;
1251*1e12ee3bSFrançois Tigeot 
1252*1e12ee3bSFrançois Tigeot 	intel_fbc_deactivate(dev_priv);
1253*1e12ee3bSFrançois Tigeot out:
1254*1e12ee3bSFrançois Tigeot 	mutex_unlock(&fbc->lock);
1255*1e12ee3bSFrançois Tigeot }
1256*1e12ee3bSFrançois Tigeot 
1257*1e12ee3bSFrançois Tigeot /**
1258*1e12ee3bSFrançois Tigeot  * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun
1259*1e12ee3bSFrançois Tigeot  * @dev_priv: i915 device instance
1260*1e12ee3bSFrançois Tigeot  *
1261*1e12ee3bSFrançois Tigeot  * Without FBC, most underruns are harmless and don't really cause too many
1262*1e12ee3bSFrançois Tigeot  * problems, except for an annoying message on dmesg. With FBC, underruns can
1263*1e12ee3bSFrançois Tigeot  * become black screens or even worse, especially when paired with bad
1264*1e12ee3bSFrançois Tigeot  * watermarks. So in order for us to be on the safe side, completely disable FBC
1265*1e12ee3bSFrançois Tigeot  * in case we ever detect a FIFO underrun on any pipe. An underrun on any pipe
1266*1e12ee3bSFrançois Tigeot  * already suggests that watermarks may be bad, so try to be as safe as
1267*1e12ee3bSFrançois Tigeot  * possible.
1268*1e12ee3bSFrançois Tigeot  *
1269*1e12ee3bSFrançois Tigeot  * This function is called from the IRQ handler.
1270*1e12ee3bSFrançois Tigeot  */
1271*1e12ee3bSFrançois Tigeot void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv)
1272*1e12ee3bSFrançois Tigeot {
1273*1e12ee3bSFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1274*1e12ee3bSFrançois Tigeot 
1275*1e12ee3bSFrançois Tigeot 	if (!fbc_supported(dev_priv))
1276*1e12ee3bSFrançois Tigeot 		return;
1277*1e12ee3bSFrançois Tigeot 
1278*1e12ee3bSFrançois Tigeot 	/* There's no guarantee that underrun_detected won't be set to true
1279*1e12ee3bSFrançois Tigeot 	 * right after this check and before the work is scheduled, but that's
1280*1e12ee3bSFrançois Tigeot 	 * not a problem since we'll check it again under the work function
1281*1e12ee3bSFrançois Tigeot 	 * while FBC is locked. This check here is just to prevent us from
1282*1e12ee3bSFrançois Tigeot 	 * unnecessarily scheduling the work, and it relies on the fact that we
1283*1e12ee3bSFrançois Tigeot 	 * never switch underrun_detect back to false after it's true. */
1284*1e12ee3bSFrançois Tigeot 	if (READ_ONCE(fbc->underrun_detected))
1285*1e12ee3bSFrançois Tigeot 		return;
1286*1e12ee3bSFrançois Tigeot 
1287*1e12ee3bSFrançois Tigeot 	schedule_work(&fbc->underrun_work);
1288*1e12ee3bSFrançois Tigeot }
1289*1e12ee3bSFrançois Tigeot 
1290c0e85e96SFrançois Tigeot /**
1291c0e85e96SFrançois Tigeot  * intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking
1292c0e85e96SFrançois Tigeot  * @dev_priv: i915 device instance
1293c0e85e96SFrançois Tigeot  *
1294c0e85e96SFrançois Tigeot  * The FBC code needs to track CRTC visibility since the older platforms can't
1295c0e85e96SFrançois Tigeot  * have FBC enabled while multiple pipes are used. This function does the
1296c0e85e96SFrançois Tigeot  * initial setup at driver load to make sure FBC is matching the real hardware.
1297c0e85e96SFrançois Tigeot  */
1298c0e85e96SFrançois Tigeot void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv)
1299c0e85e96SFrançois Tigeot {
1300c0e85e96SFrançois Tigeot 	struct intel_crtc *crtc;
1301c0e85e96SFrançois Tigeot 
1302c0e85e96SFrançois Tigeot 	/* Don't even bother tracking anything if we don't need. */
1303c0e85e96SFrançois Tigeot 	if (!no_fbc_on_multiple_pipes(dev_priv))
1304c0e85e96SFrançois Tigeot 		return;
1305c0e85e96SFrançois Tigeot 
1306303bf270SFrançois Tigeot 	for_each_intel_crtc(&dev_priv->drm, crtc)
1307c0e85e96SFrançois Tigeot 		if (intel_crtc_active(&crtc->base) &&
1308*1e12ee3bSFrançois Tigeot 		    to_intel_plane_state(crtc->base.primary->state)->base.visible)
1309c0e85e96SFrançois Tigeot 			dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe);
1310aee94f86SFrançois Tigeot }
1311aee94f86SFrançois Tigeot 
13121487f786SFrançois Tigeot /*
13131487f786SFrançois Tigeot  * The DDX driver changes its behavior depending on the value it reads from
13141487f786SFrançois Tigeot  * i915.enable_fbc, so sanitize it by translating the default value into either
13151487f786SFrançois Tigeot  * 0 or 1 in order to allow it to know what's going on.
13161487f786SFrançois Tigeot  *
13171487f786SFrançois Tigeot  * Notice that this is done at driver initialization and we still allow user
13181487f786SFrançois Tigeot  * space to change the value during runtime without sanitizing it again. IGT
13191487f786SFrançois Tigeot  * relies on being able to change i915.enable_fbc at runtime.
13201487f786SFrançois Tigeot  */
13211487f786SFrançois Tigeot static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
13221487f786SFrançois Tigeot {
13231487f786SFrançois Tigeot 	if (i915.enable_fbc >= 0)
13241487f786SFrançois Tigeot 		return !!i915.enable_fbc;
13251487f786SFrançois Tigeot 
1326bf017597SFrançois Tigeot 	if (!HAS_FBC(dev_priv))
1327bf017597SFrançois Tigeot 		return 0;
1328bf017597SFrançois Tigeot 
13291487f786SFrançois Tigeot 	if (IS_BROADWELL(dev_priv))
13301487f786SFrançois Tigeot 		return 1;
13311487f786SFrançois Tigeot 
13321487f786SFrançois Tigeot 	return 0;
13331487f786SFrançois Tigeot }
13341487f786SFrançois Tigeot 
1335bf017597SFrançois Tigeot static bool need_fbc_vtd_wa(struct drm_i915_private *dev_priv)
1336bf017597SFrançois Tigeot {
1337bf017597SFrançois Tigeot #ifdef CONFIG_INTEL_IOMMU
1338bf017597SFrançois Tigeot 	/* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
1339bf017597SFrançois Tigeot 	if (intel_iommu_gfx_mapped &&
1340bf017597SFrançois Tigeot 	    (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))) {
1341bf017597SFrançois Tigeot 		DRM_INFO("Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n");
1342bf017597SFrançois Tigeot 		return true;
1343bf017597SFrançois Tigeot 	}
1344bf017597SFrançois Tigeot #endif
1345bf017597SFrançois Tigeot 
1346bf017597SFrançois Tigeot 	return false;
1347bf017597SFrançois Tigeot }
1348bf017597SFrançois Tigeot 
1349aee94f86SFrançois Tigeot /**
13502c9916cdSFrançois Tigeot  * intel_fbc_init - Initialize FBC
13512c9916cdSFrançois Tigeot  * @dev_priv: the i915 device
13522c9916cdSFrançois Tigeot  *
13532c9916cdSFrançois Tigeot  * This function might be called during PM init process.
13542c9916cdSFrançois Tigeot  */
13552c9916cdSFrançois Tigeot void intel_fbc_init(struct drm_i915_private *dev_priv)
13562c9916cdSFrançois Tigeot {
1357c0e85e96SFrançois Tigeot 	struct intel_fbc *fbc = &dev_priv->fbc;
1358477eb7f9SFrançois Tigeot 	enum i915_pipe pipe;
1359477eb7f9SFrançois Tigeot 
1360c0e85e96SFrançois Tigeot 	INIT_WORK(&fbc->work.work, intel_fbc_work_fn);
1361*1e12ee3bSFrançois Tigeot 	INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
1362c0e85e96SFrançois Tigeot 	lockinit(&fbc->lock, "i915fl", 0, LK_CANRECURSE);
1363c0e85e96SFrançois Tigeot 	fbc->enabled = false;
1364c0e85e96SFrançois Tigeot 	fbc->active = false;
1365c0e85e96SFrançois Tigeot 	fbc->work.scheduled = false;
1366a05eeebfSFrançois Tigeot 
1367bf017597SFrançois Tigeot 	if (need_fbc_vtd_wa(dev_priv))
1368bf017597SFrançois Tigeot 		mkwrite_device_info(dev_priv)->has_fbc = false;
1369bf017597SFrançois Tigeot 
13701487f786SFrançois Tigeot 	i915.enable_fbc = intel_sanitize_fbc_option(dev_priv);
13711487f786SFrançois Tigeot 	DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", i915.enable_fbc);
13721487f786SFrançois Tigeot 
13732c9916cdSFrançois Tigeot 	if (!HAS_FBC(dev_priv)) {
1374c0e85e96SFrançois Tigeot 		fbc->no_fbc_reason = "unsupported by this chipset";
13752c9916cdSFrançois Tigeot 		return;
13762c9916cdSFrançois Tigeot 	}
13772c9916cdSFrançois Tigeot 
1378477eb7f9SFrançois Tigeot 	for_each_pipe(dev_priv, pipe) {
1379c0e85e96SFrançois Tigeot 		fbc->possible_framebuffer_bits |=
1380477eb7f9SFrançois Tigeot 				INTEL_FRONTBUFFER_PRIMARY(pipe);
1381477eb7f9SFrançois Tigeot 
1382aee94f86SFrançois Tigeot 		if (fbc_on_pipe_a_only(dev_priv))
1383477eb7f9SFrançois Tigeot 			break;
1384477eb7f9SFrançois Tigeot 	}
1385477eb7f9SFrançois Tigeot 
13862c9916cdSFrançois Tigeot 	/* This value was pulled out of someone's hat */
1387c0e85e96SFrançois Tigeot 	if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_GM45(dev_priv))
13882c9916cdSFrançois Tigeot 		I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
13892c9916cdSFrançois Tigeot 
1390aee94f86SFrançois Tigeot 	/* We still don't have any sort of hardware state readout for FBC, so
1391aee94f86SFrançois Tigeot 	 * deactivate it in case the BIOS activated it to make sure software
1392aee94f86SFrançois Tigeot 	 * matches the hardware state. */
1393c0e85e96SFrançois Tigeot 	if (intel_fbc_hw_is_active(dev_priv))
1394c0e85e96SFrançois Tigeot 		intel_fbc_hw_deactivate(dev_priv);
13952c9916cdSFrançois Tigeot }
1396