mirror of https://gitee.com/openkylin/linux.git
drm/i915: re-enable rc6 support for Ironlake+
Re-enable rc6 support on Ironlake for power savings. Adds a debugfs file to check current RC state, adds a missing workaround for Ironlake MI_SET_CONTEXT instructions, and renames MCHBAR_RENDER_STANDBY to RSTDBYCTL to match the docs. Keep RC6 and the power context disabled on pre-ILK. It only seems to hang and doesn't save any power. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
0dc79fb2a3
commit
88271da3f3
|
@ -896,7 +896,7 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
|
||||||
struct drm_device *dev = node->minor->dev;
|
struct drm_device *dev = node->minor->dev;
|
||||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
u32 rgvmodectl = I915_READ(MEMMODECTL);
|
u32 rgvmodectl = I915_READ(MEMMODECTL);
|
||||||
u32 rstdbyctl = I915_READ(MCHBAR_RENDER_STANDBY);
|
u32 rstdbyctl = I915_READ(RSTDBYCTL);
|
||||||
u16 crstandvid = I915_READ16(CRSTANDVID);
|
u16 crstandvid = I915_READ16(CRSTANDVID);
|
||||||
|
|
||||||
seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
|
seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
|
||||||
|
@ -919,6 +919,30 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
|
||||||
seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
|
seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
|
||||||
seq_printf(m, "Render standby enabled: %s\n",
|
seq_printf(m, "Render standby enabled: %s\n",
|
||||||
(rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
|
(rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
|
||||||
|
seq_printf(m, "Current RS state: ");
|
||||||
|
switch (rstdbyctl & RSX_STATUS_MASK) {
|
||||||
|
case RSX_STATUS_ON:
|
||||||
|
seq_printf(m, "on\n");
|
||||||
|
break;
|
||||||
|
case RSX_STATUS_RC1:
|
||||||
|
seq_printf(m, "RC1\n");
|
||||||
|
break;
|
||||||
|
case RSX_STATUS_RC1E:
|
||||||
|
seq_printf(m, "RC1E\n");
|
||||||
|
break;
|
||||||
|
case RSX_STATUS_RS1:
|
||||||
|
seq_printf(m, "RS1\n");
|
||||||
|
break;
|
||||||
|
case RSX_STATUS_RS2:
|
||||||
|
seq_printf(m, "RS2 (RC6)\n");
|
||||||
|
break;
|
||||||
|
case RSX_STATUS_RS3:
|
||||||
|
seq_printf(m, "RC3 (RC6+)\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
seq_printf(m, "unknown\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,8 @@
|
||||||
#define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */
|
#define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */
|
||||||
#define MI_INVALIDATE_ISP (1 << 5) /* invalidate indirect state pointers */
|
#define MI_INVALIDATE_ISP (1 << 5) /* invalidate indirect state pointers */
|
||||||
#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0)
|
#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0)
|
||||||
|
#define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0)
|
||||||
|
#define MI_SUSPEND_FLUSH_EN (1<<0)
|
||||||
#define MI_REPORT_HEAD MI_INSTR(0x07, 0)
|
#define MI_REPORT_HEAD MI_INSTR(0x07, 0)
|
||||||
#define MI_OVERLAY_FLIP MI_INSTR(0x11,0)
|
#define MI_OVERLAY_FLIP MI_INSTR(0x11,0)
|
||||||
#define MI_OVERLAY_CONTINUE (0x0<<21)
|
#define MI_OVERLAY_CONTINUE (0x0<<21)
|
||||||
|
@ -159,6 +161,7 @@
|
||||||
#define MI_MM_SPACE_PHYSICAL (0<<8)
|
#define MI_MM_SPACE_PHYSICAL (0<<8)
|
||||||
#define MI_SAVE_EXT_STATE_EN (1<<3)
|
#define MI_SAVE_EXT_STATE_EN (1<<3)
|
||||||
#define MI_RESTORE_EXT_STATE_EN (1<<2)
|
#define MI_RESTORE_EXT_STATE_EN (1<<2)
|
||||||
|
#define MI_FORCE_RESTORE (1<<1)
|
||||||
#define MI_RESTORE_INHIBIT (1<<0)
|
#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 */
|
||||||
|
@ -1131,9 +1134,50 @@
|
||||||
#define RCBMINAVG 0x111a0
|
#define RCBMINAVG 0x111a0
|
||||||
#define RCUPEI 0x111b0
|
#define RCUPEI 0x111b0
|
||||||
#define RCDNEI 0x111b4
|
#define RCDNEI 0x111b4
|
||||||
#define MCHBAR_RENDER_STANDBY 0x111b8
|
#define RSTDBYCTL 0x111b8
|
||||||
#define RCX_SW_EXIT (1<<23)
|
#define RS1EN (1<<31)
|
||||||
#define RSX_STATUS_MASK 0x00700000
|
#define RS2EN (1<<30)
|
||||||
|
#define RS3EN (1<<29)
|
||||||
|
#define D3RS3EN (1<<28) /* Display D3 imlies RS3 */
|
||||||
|
#define SWPROMORSX (1<<27) /* RSx promotion timers ignored */
|
||||||
|
#define RCWAKERW (1<<26) /* Resetwarn from PCH causes wakeup */
|
||||||
|
#define DPRSLPVREN (1<<25) /* Fast voltage ramp enable */
|
||||||
|
#define GFXTGHYST (1<<24) /* Hysteresis to allow trunk gating */
|
||||||
|
#define RCX_SW_EXIT (1<<23) /* Leave RSx and prevent re-entry */
|
||||||
|
#define RSX_STATUS_MASK (7<<20)
|
||||||
|
#define RSX_STATUS_ON (0<<20)
|
||||||
|
#define RSX_STATUS_RC1 (1<<20)
|
||||||
|
#define RSX_STATUS_RC1E (2<<20)
|
||||||
|
#define RSX_STATUS_RS1 (3<<20)
|
||||||
|
#define RSX_STATUS_RS2 (4<<20) /* aka rc6 */
|
||||||
|
#define RSX_STATUS_RSVD (5<<20) /* deep rc6 unsupported on ilk */
|
||||||
|
#define RSX_STATUS_RS3 (6<<20) /* rs3 unsupported on ilk */
|
||||||
|
#define RSX_STATUS_RSVD2 (7<<20)
|
||||||
|
#define UWRCRSXE (1<<19) /* wake counter limit prevents rsx */
|
||||||
|
#define RSCRP (1<<18) /* rs requests control on rs1/2 reqs */
|
||||||
|
#define JRSC (1<<17) /* rsx coupled to cpu c-state */
|
||||||
|
#define RS2INC0 (1<<16) /* allow rs2 in cpu c0 */
|
||||||
|
#define RS1CONTSAV_MASK (3<<14)
|
||||||
|
#define RS1CONTSAV_NO_RS1 (0<<14) /* rs1 doesn't save/restore context */
|
||||||
|
#define RS1CONTSAV_RSVD (1<<14)
|
||||||
|
#define RS1CONTSAV_SAVE_RS1 (2<<14) /* rs1 saves context */
|
||||||
|
#define RS1CONTSAV_FULL_RS1 (3<<14) /* rs1 saves and restores context */
|
||||||
|
#define NORMSLEXLAT_MASK (3<<12)
|
||||||
|
#define SLOW_RS123 (0<<12)
|
||||||
|
#define SLOW_RS23 (1<<12)
|
||||||
|
#define SLOW_RS3 (2<<12)
|
||||||
|
#define NORMAL_RS123 (3<<12)
|
||||||
|
#define RCMODE_TIMEOUT (1<<11) /* 0 is eval interval method */
|
||||||
|
#define IMPROMOEN (1<<10) /* promo is immediate or delayed until next idle interval (only for timeout method above) */
|
||||||
|
#define RCENTSYNC (1<<9) /* rs coupled to cpu c-state (3/6/7) */
|
||||||
|
#define STATELOCK (1<<7) /* locked to rs_cstate if 0 */
|
||||||
|
#define RS_CSTATE_MASK (3<<4)
|
||||||
|
#define RS_CSTATE_C367_RS1 (0<<4)
|
||||||
|
#define RS_CSTATE_C36_RS1_C7_RS2 (1<<4)
|
||||||
|
#define RS_CSTATE_RSVD (2<<4)
|
||||||
|
#define RS_CSTATE_C367_RS2 (3<<4)
|
||||||
|
#define REDSAVES (1<<3) /* no context save if was idle during rs0 */
|
||||||
|
#define REDRESTORES (1<<2) /* no restore if was idle during rs0 */
|
||||||
#define VIDCTL 0x111c0
|
#define VIDCTL 0x111c0
|
||||||
#define VIDSTS 0x111c8
|
#define VIDSTS 0x111c8
|
||||||
#define VIDSTART 0x111cc /* 8 bits */
|
#define VIDSTART 0x111cc /* 8 bits */
|
||||||
|
|
|
@ -740,7 +740,7 @@ void i915_restore_display(struct drm_device *dev)
|
||||||
I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
|
I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
|
||||||
I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
|
I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
|
||||||
I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
|
I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
|
||||||
I915_WRITE(MCHBAR_RENDER_STANDBY,
|
I915_WRITE(RSTDBYCTL,
|
||||||
dev_priv->saveMCHBAR_RENDER_STANDBY);
|
dev_priv->saveMCHBAR_RENDER_STANDBY);
|
||||||
} else {
|
} else {
|
||||||
I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
|
I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
|
||||||
|
@ -811,7 +811,7 @@ int i915_save_state(struct drm_device *dev)
|
||||||
dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
|
dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
|
||||||
dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
|
dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
|
||||||
dev_priv->saveMCHBAR_RENDER_STANDBY =
|
dev_priv->saveMCHBAR_RENDER_STANDBY =
|
||||||
I915_READ(MCHBAR_RENDER_STANDBY);
|
I915_READ(RSTDBYCTL);
|
||||||
} else {
|
} else {
|
||||||
dev_priv->saveIER = I915_READ(IER);
|
dev_priv->saveIER = I915_READ(IER);
|
||||||
dev_priv->saveIMR = I915_READ(IMR);
|
dev_priv->saveIMR = I915_READ(IMR);
|
||||||
|
|
|
@ -6420,35 +6420,37 @@ void intel_enable_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) && 0) { /* XXX causes a failure during suspend */
|
if (IS_IRONLAKE_M(dev)) {
|
||||||
if (dev_priv->renderctx == NULL)
|
if (dev_priv->renderctx == NULL)
|
||||||
dev_priv->renderctx = intel_alloc_context_page(dev);
|
dev_priv->renderctx = intel_alloc_context_page(dev);
|
||||||
if (dev_priv->renderctx) {
|
if (dev_priv->renderctx) {
|
||||||
struct drm_i915_gem_object *obj = dev_priv->renderctx;
|
struct drm_i915_gem_object *obj = dev_priv->renderctx;
|
||||||
if (BEGIN_LP_RING(4) == 0) {
|
if (BEGIN_LP_RING(6) != 0) {
|
||||||
OUT_RING(MI_SET_CONTEXT);
|
i915_gem_object_unpin(obj);
|
||||||
OUT_RING(obj->gtt_offset |
|
drm_gem_object_unreference(&obj->base);
|
||||||
MI_MM_SPACE_GTT |
|
dev_priv->renderctx = NULL;
|
||||||
MI_SAVE_EXT_STATE_EN |
|
return;
|
||||||
MI_RESTORE_EXT_STATE_EN |
|
|
||||||
MI_RESTORE_INHIBIT);
|
|
||||||
OUT_RING(MI_NOOP);
|
|
||||||
OUT_RING(MI_FLUSH);
|
|
||||||
ADVANCE_LP_RING();
|
|
||||||
}
|
}
|
||||||
|
OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
|
||||||
|
OUT_RING(MI_SET_CONTEXT);
|
||||||
|
OUT_RING(obj->gtt_offset |
|
||||||
|
MI_MM_SPACE_GTT |
|
||||||
|
MI_SAVE_EXT_STATE_EN |
|
||||||
|
MI_RESTORE_EXT_STATE_EN |
|
||||||
|
MI_RESTORE_INHIBIT);
|
||||||
|
OUT_RING(MI_SUSPEND_FLUSH);
|
||||||
|
OUT_RING(MI_NOOP);
|
||||||
|
OUT_RING(MI_FLUSH);
|
||||||
|
ADVANCE_LP_RING();
|
||||||
} else
|
} else
|
||||||
DRM_DEBUG_KMS("Failed to allocate render context."
|
DRM_DEBUG_KMS("Failed to allocate render context."
|
||||||
"Disable RC6\n");
|
"Disable RC6\n");
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_GEN4(dev) && IS_MOBILE(dev)) {
|
|
||||||
if (dev_priv->pwrctx == NULL)
|
if (dev_priv->pwrctx == NULL)
|
||||||
dev_priv->pwrctx = intel_alloc_context_page(dev);
|
dev_priv->pwrctx = intel_alloc_context_page(dev);
|
||||||
if (dev_priv->pwrctx) {
|
if (dev_priv->pwrctx) {
|
||||||
struct drm_i915_gem_object *obj = dev_priv->pwrctx;
|
struct drm_i915_gem_object *obj = dev_priv->pwrctx;
|
||||||
I915_WRITE(PWRCTXA, obj->gtt_offset | PWRCTX_EN);
|
I915_WRITE(PWRCTXA, obj->gtt_offset | PWRCTX_EN);
|
||||||
I915_WRITE(MCHBAR_RENDER_STANDBY,
|
|
||||||
I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue