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