[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