drm/i915: add render standby support
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>
This commit is contained in:
parent
d8a2d0e00c
commit
97f5ab6651
|
@ -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;
|
||||
|
||||
|
@ -280,6 +281,7 @@ typedef struct drm_i915_private {
|
|||
u32 saveDSPBCNTR;
|
||||
u32 saveDSPARB;
|
||||
u32 saveRENDERSTANDBY;
|
||||
u32 savePWRCTXA;
|
||||
u32 saveHWS;
|
||||
u32 savePIPEACONF;
|
||||
u32 savePIPEBCONF;
|
||||
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue