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: Zou Nan hai <nanhai.zou@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>

authored by

Zou Nan hai and committed by
Eric Anholt
aa40d6bb 1cafd347

+55 -10
+1
drivers/gpu/drm/i915/i915_drv.h
··· 254 drm_local_map_t hws_map; 255 struct drm_gem_object *seqno_obj; 256 struct drm_gem_object *pwrctx; 257 258 struct resource mch_res; 259
··· 254 drm_local_map_t hws_map; 255 struct drm_gem_object *seqno_obj; 256 struct drm_gem_object *pwrctx; 257 + struct drm_gem_object *renderctx; 258 259 struct resource mch_res; 260
+11
drivers/gpu/drm/i915/i915_reg.h
··· 181 #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) 182 #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) 183 #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) 184 #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) 185 #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ 186 #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) ··· 1106 #define DDRMPLL1 0X12c20 1107 #define PEG_BAND_GAP_DATA 0x14d68 1108 1109 /* 1110 * Overlay regs 1111 */
··· 181 #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) 182 #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) 183 #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) 184 + #define MI_SET_CONTEXT MI_INSTR(0x18, 0) 185 + #define MI_MM_SPACE_GTT (1<<8) 186 + #define MI_MM_SPACE_PHYSICAL (0<<8) 187 + #define MI_SAVE_EXT_STATE_EN (1<<3) 188 + #define MI_RESTORE_EXT_STATE_EN (1<<2) 189 + #define MI_RESTORE_INHIBIT (1<<0) 190 #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) 191 #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ 192 #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) ··· 1100 #define DDRMPLL1 0X12c20 1101 #define PEG_BAND_GAP_DATA 0x14d68 1102 1103 + /* 1104 + * Logical Context regs 1105 + */ 1106 + #define CCID 0x2180 1107 + #define CCID_EN (1<<0) 1108 /* 1109 * Overlay regs 1110 */
+43 -10
drivers/gpu/drm/i915/intel_display.c
··· 5466 }; 5467 5468 static struct drm_gem_object * 5469 - intel_alloc_power_context(struct drm_device *dev) 5470 { 5471 - struct drm_gem_object *pwrctx; 5472 int ret; 5473 5474 - pwrctx = i915_gem_alloc_object(dev, 4096); 5475 - if (!pwrctx) { 5476 DRM_DEBUG("failed to alloc power context, RC6 disabled\n"); 5477 return NULL; 5478 } 5479 5480 mutex_lock(&dev->struct_mutex); 5481 - ret = i915_gem_object_pin(pwrctx, 4096); 5482 if (ret) { 5483 DRM_ERROR("failed to pin power context: %d\n", ret); 5484 goto err_unref; 5485 } 5486 5487 - ret = i915_gem_object_set_to_gtt_domain(pwrctx, 1); 5488 if (ret) { 5489 DRM_ERROR("failed to set-domain on power context: %d\n", ret); 5490 goto err_unpin; 5491 } 5492 mutex_unlock(&dev->struct_mutex); 5493 5494 - return pwrctx; 5495 5496 err_unpin: 5497 - i915_gem_object_unpin(pwrctx); 5498 err_unref: 5499 - drm_gem_object_unreference(pwrctx); 5500 mutex_unlock(&dev->struct_mutex); 5501 return NULL; 5502 } ··· 5796 * GPU can automatically power down the render unit if given a page 5797 * to save state. 5798 */ 5799 if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { 5800 struct drm_i915_gem_object *obj_priv = NULL; 5801 ··· 5827 } else { 5828 struct drm_gem_object *pwrctx; 5829 5830 - pwrctx = intel_alloc_power_context(dev); 5831 if (pwrctx) { 5832 dev_priv->pwrctx = pwrctx; 5833 obj_priv = to_intel_bo(pwrctx); ··· 6084 6085 if (dev_priv->display.disable_fbc) 6086 dev_priv->display.disable_fbc(dev); 6087 6088 if (dev_priv->pwrctx) { 6089 struct drm_i915_gem_object *obj_priv;
··· 5466 }; 5467 5468 static struct drm_gem_object * 5469 + intel_alloc_context_page(struct drm_device *dev) 5470 { 5471 + struct drm_gem_object *ctx; 5472 int ret; 5473 5474 + ctx = i915_gem_alloc_object(dev, 4096); 5475 + if (!ctx) { 5476 DRM_DEBUG("failed to alloc power context, RC6 disabled\n"); 5477 return NULL; 5478 } 5479 5480 mutex_lock(&dev->struct_mutex); 5481 + ret = i915_gem_object_pin(ctx, 4096); 5482 if (ret) { 5483 DRM_ERROR("failed to pin power context: %d\n", ret); 5484 goto err_unref; 5485 } 5486 5487 + ret = i915_gem_object_set_to_gtt_domain(ctx, 1); 5488 if (ret) { 5489 DRM_ERROR("failed to set-domain on power context: %d\n", ret); 5490 goto err_unpin; 5491 } 5492 mutex_unlock(&dev->struct_mutex); 5493 5494 + return ctx; 5495 5496 err_unpin: 5497 + i915_gem_object_unpin(ctx); 5498 err_unref: 5499 + drm_gem_object_unreference(ctx); 5500 mutex_unlock(&dev->struct_mutex); 5501 return NULL; 5502 } ··· 5796 * GPU can automatically power down the render unit if given a page 5797 * to save state. 5798 */ 5799 + if (IS_IRONLAKE_M(dev)) { 5800 + if (dev_priv->renderctx == NULL) 5801 + dev_priv->renderctx = intel_alloc_context_page(dev); 5802 + if (dev_priv->renderctx) { 5803 + struct drm_i915_gem_object *obj_priv; 5804 + obj_priv = to_intel_bo(dev_priv->renderctx); 5805 + if (obj_priv) { 5806 + BEGIN_LP_RING(4); 5807 + OUT_RING(MI_SET_CONTEXT); 5808 + OUT_RING(obj_priv->gtt_offset | 5809 + MI_MM_SPACE_GTT | 5810 + MI_SAVE_EXT_STATE_EN | 5811 + MI_RESTORE_EXT_STATE_EN | 5812 + MI_RESTORE_INHIBIT); 5813 + OUT_RING(MI_NOOP); 5814 + OUT_RING(MI_FLUSH); 5815 + ADVANCE_LP_RING(); 5816 + } 5817 + } else 5818 + DRM_DEBUG_KMS("Failed to allocate render context." 5819 + "Disable RC6\n"); 5820 + } 5821 + 5822 if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { 5823 struct drm_i915_gem_object *obj_priv = NULL; 5824 ··· 5804 } else { 5805 struct drm_gem_object *pwrctx; 5806 5807 + pwrctx = intel_alloc_context_page(dev); 5808 if (pwrctx) { 5809 dev_priv->pwrctx = pwrctx; 5810 obj_priv = to_intel_bo(pwrctx); ··· 6061 6062 if (dev_priv->display.disable_fbc) 6063 dev_priv->display.disable_fbc(dev); 6064 + 6065 + if (dev_priv->renderctx) { 6066 + struct drm_i915_gem_object *obj_priv; 6067 + 6068 + obj_priv = to_intel_bo(dev_priv->renderctx); 6069 + I915_WRITE(CCID, obj_priv->gtt_offset &~ CCID_EN); 6070 + I915_READ(CCID); 6071 + i915_gem_object_unpin(dev_priv->renderctx); 6072 + drm_gem_object_unreference(dev_priv->renderctx); 6073 + } 6074 6075 if (dev_priv->pwrctx) { 6076 struct drm_i915_gem_object *obj_priv;