Commit aa40d6bb authored by Zou Nan hai's avatar Zou Nan hai Committed by Eric Anholt

drm/i915: Set up a render context on Ironlake

RC6 power state requires a logical render context in place for saving
render context.
Signed-off-by: default avatarZou Nan hai <nanhai.zou@intel.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 1cafd347
...@@ -254,6 +254,7 @@ typedef struct drm_i915_private { ...@@ -254,6 +254,7 @@ typedef struct drm_i915_private {
drm_local_map_t hws_map; drm_local_map_t hws_map;
struct drm_gem_object *seqno_obj; struct drm_gem_object *seqno_obj;
struct drm_gem_object *pwrctx; struct drm_gem_object *pwrctx;
struct drm_gem_object *renderctx;
struct resource mch_res; struct resource mch_res;
......
...@@ -181,6 +181,12 @@ ...@@ -181,6 +181,12 @@
#define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2)
#define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1)
#define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
#define MI_SET_CONTEXT MI_INSTR(0x18, 0)
#define MI_MM_SPACE_GTT (1<<8)
#define MI_MM_SPACE_PHYSICAL (0<<8)
#define MI_SAVE_EXT_STATE_EN (1<<3)
#define MI_RESTORE_EXT_STATE_EN (1<<2)
#define MI_RESTORE_INHIBIT (1<<0)
#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1)
#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
...@@ -1100,6 +1106,11 @@ ...@@ -1100,6 +1106,11 @@
#define DDRMPLL1 0X12c20 #define DDRMPLL1 0X12c20
#define PEG_BAND_GAP_DATA 0x14d68 #define PEG_BAND_GAP_DATA 0x14d68
/*
* Logical Context regs
*/
#define CCID 0x2180
#define CCID_EN (1<<0)
/* /*
* Overlay regs * Overlay regs
*/ */
......
...@@ -5466,37 +5466,37 @@ static const struct drm_mode_config_funcs intel_mode_funcs = { ...@@ -5466,37 +5466,37 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
}; };
static struct drm_gem_object * static struct drm_gem_object *
intel_alloc_power_context(struct drm_device *dev) intel_alloc_context_page(struct drm_device *dev)
{ {
struct drm_gem_object *pwrctx; struct drm_gem_object *ctx;
int ret; int ret;
pwrctx = i915_gem_alloc_object(dev, 4096); ctx = i915_gem_alloc_object(dev, 4096);
if (!pwrctx) { if (!ctx) {
DRM_DEBUG("failed to alloc power context, RC6 disabled\n"); DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
return NULL; return NULL;
} }
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
ret = i915_gem_object_pin(pwrctx, 4096); ret = i915_gem_object_pin(ctx, 4096);
if (ret) { if (ret) {
DRM_ERROR("failed to pin power context: %d\n", ret); DRM_ERROR("failed to pin power context: %d\n", ret);
goto err_unref; goto err_unref;
} }
ret = i915_gem_object_set_to_gtt_domain(pwrctx, 1); ret = i915_gem_object_set_to_gtt_domain(ctx, 1);
if (ret) { if (ret) {
DRM_ERROR("failed to set-domain on power context: %d\n", ret); DRM_ERROR("failed to set-domain on power context: %d\n", ret);
goto err_unpin; goto err_unpin;
} }
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return pwrctx; return ctx;
err_unpin: err_unpin:
i915_gem_object_unpin(pwrctx); i915_gem_object_unpin(ctx);
err_unref: err_unref:
drm_gem_object_unreference(pwrctx); drm_gem_object_unreference(ctx);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return NULL; return NULL;
} }
...@@ -5796,6 +5796,29 @@ void intel_init_clock_gating(struct drm_device *dev) ...@@ -5796,6 +5796,29 @@ void intel_init_clock_gating(struct drm_device *dev)
* GPU can automatically power down the render unit if given a page * GPU can automatically power down the render unit if given a page
* to save state. * to save state.
*/ */
if (IS_IRONLAKE_M(dev)) {
if (dev_priv->renderctx == NULL)
dev_priv->renderctx = intel_alloc_context_page(dev);
if (dev_priv->renderctx) {
struct drm_i915_gem_object *obj_priv;
obj_priv = to_intel_bo(dev_priv->renderctx);
if (obj_priv) {
BEGIN_LP_RING(4);
OUT_RING(MI_SET_CONTEXT);
OUT_RING(obj_priv->gtt_offset |
MI_MM_SPACE_GTT |
MI_SAVE_EXT_STATE_EN |
MI_RESTORE_EXT_STATE_EN |
MI_RESTORE_INHIBIT);
OUT_RING(MI_NOOP);
OUT_RING(MI_FLUSH);
ADVANCE_LP_RING();
}
} else
DRM_DEBUG_KMS("Failed to allocate render context."
"Disable RC6\n");
}
if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) {
struct drm_i915_gem_object *obj_priv = NULL; struct drm_i915_gem_object *obj_priv = NULL;
...@@ -5804,7 +5827,7 @@ void intel_init_clock_gating(struct drm_device *dev) ...@@ -5804,7 +5827,7 @@ void intel_init_clock_gating(struct drm_device *dev)
} else { } else {
struct drm_gem_object *pwrctx; struct drm_gem_object *pwrctx;
pwrctx = intel_alloc_power_context(dev); pwrctx = intel_alloc_context_page(dev);
if (pwrctx) { if (pwrctx) {
dev_priv->pwrctx = pwrctx; dev_priv->pwrctx = pwrctx;
obj_priv = to_intel_bo(pwrctx); obj_priv = to_intel_bo(pwrctx);
...@@ -6062,6 +6085,16 @@ void intel_modeset_cleanup(struct drm_device *dev) ...@@ -6062,6 +6085,16 @@ void intel_modeset_cleanup(struct drm_device *dev)
if (dev_priv->display.disable_fbc) if (dev_priv->display.disable_fbc)
dev_priv->display.disable_fbc(dev); dev_priv->display.disable_fbc(dev);
if (dev_priv->renderctx) {
struct drm_i915_gem_object *obj_priv;
obj_priv = to_intel_bo(dev_priv->renderctx);
I915_WRITE(CCID, obj_priv->gtt_offset &~ CCID_EN);
I915_READ(CCID);
i915_gem_object_unpin(dev_priv->renderctx);
drm_gem_object_unreference(dev_priv->renderctx);
}
if (dev_priv->pwrctx) { if (dev_priv->pwrctx) {
struct drm_i915_gem_object *obj_priv; struct drm_i915_gem_object *obj_priv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment