Skip to content

Commit

Permalink
drm/i915: add render standby support
Browse files Browse the repository at this point in the history
Render standy allows the GPU to power down the render unit when idle.
In order for this to work, it needs a page of graphics memory to save
state.  This patch allocates that page and enables the feature on
supported chipsets.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
  • Loading branch information
Jesse Barnes authored and Eric Anholt committed Nov 5, 2009
1 parent d8a2d0e commit 97f5ab6
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 3 deletions.
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ typedef struct drm_i915_private {
unsigned int status_gfx_addr;
drm_local_map_t hws_map;
struct drm_gem_object *hws_obj;
struct drm_gem_object *pwrctx;

struct resource mch_res;

Expand Down Expand Up @@ -280,6 +281,7 @@ typedef struct drm_i915_private {
u32 saveDSPBCNTR;
u32 saveDSPARB;
u32 saveRENDERSTANDBY;
u32 savePWRCTXA;
u32 saveHWS;
u32 savePIPEACONF;
u32 savePIPEBCONF;
Expand Down Expand Up @@ -1019,6 +1021,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
(IS_I9XX(dev) || IS_GM45(dev)) && \
!IS_IGD(dev) && \
!IS_IGDNG(dev))
#define I915_HAS_RC6(dev) (IS_I965GM(dev) || IS_GM45(dev) || IS_IGDNG_M(dev))

#define PRIMARY_RINGBUFFER_SIZE (128*1024)

Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@
#define HWS_PGA 0x02080
#define HWS_ADDRESS_MASK 0xfffff000
#define HWS_START_ADDRESS_SHIFT 4
#define PWRCTXA 0x2088 /* 965GM+ only */
#define PWRCTX_EN (1<<0)
#define IPEIR 0x02088
#define IPEHR 0x0208c
#define INSTDONE 0x02090
Expand Down Expand Up @@ -769,7 +771,8 @@

/** GM965 GM45 render standby register */
#define MCHBAR_RENDER_STANDBY 0x111B8

#define RCX_SW_EXIT (1<<23)
#define RSX_STATUS_MASK 0x00700000
#define PEG_BAND_GAP_DATA 0x14d68

/*
Expand Down
8 changes: 6 additions & 2 deletions drivers/gpu/drm/i915/i915_suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,10 @@ int i915_save_state(struct drm_device *dev)
pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);

/* Render Standby */
if (IS_I965G(dev) && IS_MOBILE(dev))
if (I915_HAS_RC6(dev)) {
dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
dev_priv->savePWRCTXA = I915_READ(PWRCTXA);
}

/* Hardware status page */
dev_priv->saveHWS = I915_READ(HWS_PGA);
Expand Down Expand Up @@ -762,8 +764,10 @@ int i915_restore_state(struct drm_device *dev)
pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);

/* Render Standby */
if (IS_I965G(dev) && IS_MOBILE(dev))
if (I915_HAS_RC6(dev)) {
I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA);
}

/* Hardware status page */
I915_WRITE(HWS_PGA, dev_priv->saveHWS);
Expand Down
41 changes: 41 additions & 0 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -4296,6 +4296,42 @@ void intel_init_clock_gating(struct drm_device *dev)
} else if (IS_I830(dev)) {
I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
}

/*
* GPU can automatically power down the render unit if given a page
* to save state.
*/
if (I915_HAS_RC6(dev)) {
struct drm_gem_object *pwrctx;
struct drm_i915_gem_object *obj_priv;
int ret;

pwrctx = drm_gem_object_alloc(dev, 4096);
if (!pwrctx) {
DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
goto out;
}

ret = i915_gem_object_pin(pwrctx, 4096);
if (ret) {
DRM_ERROR("failed to pin power context: %d\n", ret);
drm_gem_object_unreference(pwrctx);
goto out;
}

i915_gem_object_set_to_gtt_domain(pwrctx, 1);

obj_priv = pwrctx->driver_private;

I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN);
I915_WRITE(MCHBAR_RENDER_STANDBY,
I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);

dev_priv->pwrctx = pwrctx;
}

out:
return;
}

/* Set up chip specific display functions */
Expand Down Expand Up @@ -4450,6 +4486,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
if (dev_priv->display.disable_fbc)
dev_priv->display.disable_fbc(dev);

if (dev_priv->pwrctx) {
i915_gem_object_unpin(dev_priv->pwrctx);
drm_gem_object_unreference(dev_priv->pwrctx);
}

drm_mode_config_cleanup(dev);
}

Expand Down

0 comments on commit 97f5ab6

Please sign in to comment.