[Intel-gfx] [PATCH 1/3] drm/i915: Add the frame buffer compression on Ironlake

ykzhao yakui.zhao at intel.com
Thu Apr 1 04:07:16 CEST 2010


On Tue, 2010-03-23 at 11:02 +0800, Zhenyu Wang wrote:
> From: Zhao Yakui <yakui.zhao at intel.com>

Please ignore this patch.

Now when trying to enable both the CxSR and FBC, we meet a flicker
issue. And in the test the two features can't work together. Of course
if only one of two features is enabled, there is no flicker. As the
self-refresh has more significant power saving effect, we want to add
the support of memory self-refresh firstly.

Thanks


> 
> Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
> Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c      |   10 ++--
>  drivers/gpu/drm/i915/i915_drv.c      |    2 +-
>  drivers/gpu/drm/i915/i915_drv.h      |    1 +
>  drivers/gpu/drm/i915/i915_reg.h      |   20 +++++++
>  drivers/gpu/drm/i915/i915_suspend.c  |    9 +++-
>  drivers/gpu/drm/i915/intel_display.c |   92 +++++++++++++++++++++++++++++++++-
>  6 files changed, 126 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index a9f8589..902d286 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1332,7 +1332,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
>                 drm_mm_put_block(compressed_fb);
>         }
> 
> -       if (!IS_GM45(dev)) {
> +       if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) {
>                 compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
>                                                     4096, 0);
>                 if (!compressed_llb) {
> @@ -1355,8 +1355,10 @@ static void i915_setup_compression(struct drm_device *dev, int size)
>         }
> 
>         dev_priv->cfb_size = size;
> -
> -       if (IS_GM45(dev)) {
> +       if (IS_IRONLAKE_M(dev)) {
> +               ironlake_disable_fbc(dev);
> +               I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
> +       } else if (IS_GM45(dev)) {
>                 g4x_disable_fbc(dev);
>                 I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
>         } else {
> @@ -1365,7 +1367,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
>                 I915_WRITE(FBC_LL_BASE, ll_base);
>         }
> 
> -       DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
> +       DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
>                   ll_base, size >> 20);
>  }
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 4b26919..e5656c1 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -133,7 +133,7 @@ const static struct intel_device_info intel_ironlake_d_info = {
> 
>  const static struct intel_device_info intel_ironlake_m_info = {
>         .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
> -       .need_gfx_hws = 1, .has_rc6 = 1,
> +       .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
>         .has_hotplug = 1,
>  };
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 73acf18..4e6a5de 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -989,6 +989,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
>  extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
>  extern void i8xx_disable_fbc(struct drm_device *dev);
>  extern void g4x_disable_fbc(struct drm_device *dev);
> +extern void ironlake_disable_fbc(struct drm_device *dev);
> 
>  /**
>   * Lock test for when it's just for synchronization of ring access.
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 6040c36..36ebc12 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -421,6 +421,26 @@
>  #define DPFC_CHICKEN           0x3224
>  #define   DPFC_HT_MODIFY       (1<<31)
> 
> +/* Framebuffer compression for Ironlake */
> +#define ILK_DPFC_CB_BASE       0x43200
> +#define ILK_DPFC_CONTROL       0x43208
> +/* The bit 28-8 is reserved */
> +#define   DPFC_RESERVED                (0x1FFFFF00)
> +#define ILK_DPFC_RECOMP_CTL    0x4320c
> +#define ILK_DPFC_STATUS                0x43210
> +#define ILK_DPFC_FENCE_YOFF    0x43218
> +#define ILK_DPFC_CHICKEN       0x43224
> +#define ILK_FBC_RT_BASE                0x2128
> +#define   ILK_FBC_RT_VALID     (1<<0)
> +
> +#define ILK_DISPLAY_CHICKEN1   0x42000
> +#define   ILK_FBCQ_DIS         (1<<22)
> +#define ILK_DISPLAY_CHICKEN2   0x42004
> +/* According to the spec this bit 22 of 0x420004 should be enabled */
> +#define   ILK_DPARB_GATE       (1<<22)
> +#define ILK_DSPCLK_GATE                0x42020
> +/* This bit 7 of 0x42020 should be enabled to enable the FBC */
> +#define   ILK_CLK_FBC          (1<<7)
>  /*
>   * GPIO regs
>   */
> diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
> index ac0d1a7..abfe4d0 100644
> --- a/drivers/gpu/drm/i915/i915_suspend.c
> +++ b/drivers/gpu/drm/i915/i915_suspend.c
> @@ -601,7 +601,9 @@ void i915_save_display(struct drm_device *dev)
>         /* FIXME: save TV & SDVO state */
> 
>         /* FBC state */
> -       if (IS_GM45(dev)) {
> +       if (IS_IRONLAKE_M(dev))
> +               dev_priv->saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
> +       else if (IS_GM45(dev)) {
>                 dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
>         } else {
>                 dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
> @@ -703,7 +705,10 @@ void i915_restore_display(struct drm_device *dev)
>         /* FIXME: restore TV & SDVO state */
> 
>         /* FBC info */
> -       if (IS_GM45(dev)) {
> +       if (IS_IRONLAKE_M(dev)) {
> +               ironlake_disable_fbc(dev);
> +               I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
> +       } else if (IS_GM45(dev)) {
>                 g4x_disable_fbc(dev);
>                 I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
>         } else {
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index f9a32a4..fe15fa1 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1130,6 +1130,68 @@ static bool g4x_fbc_enabled(struct drm_crtc *crtc)
>         return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
>  }
> 
> +static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct drm_framebuffer *fb = crtc->fb;
> +       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> +       struct drm_i915_gem_object *obj_priv = intel_fb->obj->driver_private;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA :
> +                    DPFC_CTL_PLANEB);
> +       unsigned long stall_watermark = 200;
> +       u32 dpfc_ctl;
> +
> +       dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
> +       dev_priv->cfb_fence = obj_priv->fence_reg;
> +       dev_priv->cfb_plane = intel_crtc->plane;
> +
> +       dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
> +       dpfc_ctl &= DPFC_RESERVED;
> +       dpfc_ctl |= plane | DPFC_CTL_LIMIT_1X;
> +       if (obj_priv->tiling_mode != I915_TILING_NONE) {
> +               dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence;
> +               I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
> +       } else {
> +               I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY);
> +       }
> +
> +       I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
> +       I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
> +                  (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
> +                  (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
> +       I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
> +       I915_WRITE(ILK_FBC_RT_BASE, obj_priv->gtt_offset | ILK_FBC_RT_VALID);
> +       /* enable it... */
> +       I915_WRITE(ILK_DPFC_CONTROL, I915_READ(ILK_DPFC_CONTROL) |
> +                                       DPFC_CTL_EN);
> +
> +       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
> +}
> +
> +void ironlake_disable_fbc(struct drm_device *dev)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       u32 dpfc_ctl;
> +
> +       /* Disable compression */
> +       dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
> +       dpfc_ctl &= ~DPFC_CTL_EN;
> +       I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
> +       intel_wait_for_vblank(dev);
> +
> +       DRM_DEBUG_KMS("disabled FBC\n");
> +}
> +
> +static bool ironlake_fbc_enabled(struct drm_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
> +}
> +
>  /**
>   * intel_update_fbc - enable/disable FBC as needed
>   * @crtc: CRTC to point the compressor at
> @@ -1756,6 +1818,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
> 
>                 intel_crtc_load_lut(crtc);
> 
> +               intel_update_fbc(crtc, &crtc->mode);
> +
>         break;
>         case DRM_MODE_DPMS_OFF:
>                 DRM_DEBUG_KMS("crtc %d dpms off\n", pipe);
> @@ -1770,6 +1834,10 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
>                         I915_READ(dspbase_reg);
>                 }
> 
> +               if (dev_priv->cfb_plane == plane &&
> +                   dev_priv->display.disable_fbc)
> +                       dev_priv->display.disable_fbc(dev);
> +
>                 i915_disable_vga(dev);
> 
>                 /* disable cpu pipe, disable after all planes disabled */
> @@ -4716,6 +4784,24 @@ void intel_init_clock_gating(struct drm_device *dev)
>          * specs, but enable as much else as we can.
>          */
>         if (HAS_PCH_SPLIT(dev)) {
> +               /*
> +                * According to the spec the following bits should be set in
> +                * order to enable FBC
> +                * The bit 22 of 0x42000
> +                * The bit 22 of 0x42004
> +                * The bit 7 of 0x42020
> +                */
> +               if (IS_IRONLAKE_M(dev)) {
> +                       I915_WRITE(ILK_DISPLAY_CHICKEN1,
> +                                       (I915_READ(ILK_DISPLAY_CHICKEN1) |
> +                                               ILK_FBCQ_DIS));
> +                       I915_WRITE(ILK_DISPLAY_CHICKEN2,
> +                                       (I915_READ(ILK_DISPLAY_CHICKEN2) |
> +                                               ILK_DPARB_GATE));
> +                       I915_WRITE(ILK_DSPCLK_GATE,
> +                                       (I915_READ(ILK_DSPCLK_GATE) |
> +                                               ILK_CLK_FBC));
> +               }
>                 return;
>         } else if (IS_G4X(dev)) {
>                 uint32_t dspclk_gate;
> @@ -4795,7 +4881,11 @@ static void intel_init_display(struct drm_device *dev)
> 
>         /* Only mobile has FBC, leave pointers NULL for other chips */
>         if (IS_MOBILE(dev)) {
> -               if (IS_GM45(dev)) {
> +               if (IS_IRONLAKE_M(dev)) {
> +                       dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
> +                       dev_priv->display.enable_fbc = ironlake_enable_fbc;
> +                       dev_priv->display.disable_fbc = ironlake_disable_fbc;
> +               } else if (IS_GM45(dev)) {
>                         dev_priv->display.fbc_enabled = g4x_fbc_enabled;
>                         dev_priv->display.enable_fbc = g4x_enable_fbc;
>                         dev_priv->display.disable_fbc = g4x_disable_fbc;
> --
> 1.6.3.3
> 




More information about the Intel-gfx mailing list