[Intel-gfx] [PATCH] drm/i915: enable rc6 support on Ironlake

Jesse Barnes jbarnes at virtuousgeek.org
Wed Dec 22 21:00:15 CET 2010


On Tue, 21 Dec 2010 15:11:00 -0800
Jesse Barnes <jbarnes at virtuousgeek.org> wrote:

> Doesn't actually work right now, but I did manage to get into rc6 once
> and see a lot of power savings (over 1W).
> ---

This one works better (doesn't hang the GPU, I think because I was
missing the CRSTANDVID programming earlier).  However, RSTDBYCTL
indicates that my machine only gets to RC1, or trunk clock gating, so
there's probably more power to be saved.  That said, this patch by
itself seems to save a little power.

-- 
Jesse Barnes, Intel Open Source Technology Center

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 232479c..fcaa352 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -161,6 +161,7 @@
 #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_FORCE_RESTORE		(1<<1)
 #define   MI_RESTORE_INHIBIT		(1<<0)
 #define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */
@@ -1133,12 +1134,49 @@
 #define RCUPEI			0x111b0
 #define RCDNEI			0x111b4
 #define MCHBAR_RENDER_STANDBY		0x111b8
-#define   RS1_ENABLE		(1<<31)
-#define   RS2_ENABLE		(1<<30)
-#define   RS3_ENABLE		(1<<29)
-#define   RCX_SW_EXIT		(1<<23)
-#define   RSX_STATUS_MASK	0x00700000
-#define   RC_CSTATE_RS2		(3<<4)
+#define   RS1EN			(1<<31)
+#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<<23)
+#define   RSX_STATUS_ON		(0<<23)
+#define   RSX_STATUS_RC1	(1<<23)
+#define   RSX_STATUS_RC1E	(2<<23)
+#define   RSX_STATUS_RS1	(3<<23)
+#define   RSX_STATUS_RS2	(4<<23) /* aka rc6 */
+#define   RSX_STATUS_RSVD	(5<<23) /* deep rc6 unsupported on ilk */
+#define   RSX_STATUS_RS3	(6<<23) /* rs3 unsupported on ilk */
+#define   RSX_STATUS_RSVD2	(7<<23)
+#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 VIDSTS			0x111c8
 #define VIDSTART		0x111cc /* 8 bits */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3d53e13..ec396c9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6368,22 +6368,11 @@ void intel_enable_clock_gating(struct drm_device *dev)
 		I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
 	}
 
-	if ((IS_GEN4(dev) || IS_GEN5(dev)) && IS_MOBILE(dev)) {
-		if (dev_priv->pwrctx == NULL)
-			dev_priv->pwrctx = intel_alloc_context_page(dev);
-		if (dev_priv->pwrctx) {
-			struct drm_i915_gem_object *obj = dev_priv->pwrctx;
-			I915_WRITE(PWRCTXA, obj->gtt_offset | PWRCTX_EN);
-			I915_WRITE(MCHBAR_RENDER_STANDBY,
-				   (I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT) | RS1_ENABLE | RS2_ENABLE | RC_CSTATE_RS2);
-		}
-	}
-
 	/*
 	 * GPU can automatically power down the render unit if given a page
 	 * to save state.
 	 */
-	if (IS_IRONLAKE_M(dev)) {
+	if (IS_IRONLAKE_M(dev) && dev_priv->pwrctx) {
 		if (dev_priv->renderctx == NULL)
 			dev_priv->renderctx = intel_alloc_context_page(dev);
 		if (dev_priv->renderctx) {
@@ -6406,6 +6395,38 @@ void intel_enable_clock_gating(struct drm_device *dev)
 				       "Disable RC6\n");
 	}
 
+	if ((IS_GEN4(dev) || IS_GEN5(dev)) && IS_MOBILE(dev)) {
+		if (dev_priv->pwrctx == NULL)
+			dev_priv->pwrctx = intel_alloc_context_page(dev);
+		if (dev_priv->pwrctx) {
+			struct drm_i915_gem_object *obj = dev_priv->pwrctx;
+			u32 rstdby;
+
+			I915_WRITE(PWRCTXA, obj->gtt_offset | PWRCTX_EN);
+			I915_WRITE(CRSTANDVID, 0x808);
+
+			rstdby = RS1EN | RS2EN | SWPROMORSX | DPRSLPVREN | GFXTGHYST |
+				RS2INC0 | NORMAL_RS123 | STATELOCK;
+			I915_WRITE(MCHBAR_RENDER_STANDBY, rstdby);
+		}
+	}
+
+	if (IS_IRONLAKE_M(dev) && dev_priv->renderctx) {
+		struct drm_i915_gem_object *obj = dev_priv->renderctx;
+
+		BEGIN_LP_RING(6);
+		OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
+		OUT_RING(MI_SET_CONTEXT);
+		OUT_RING(MI_SUSPEND_FLUSH);
+		OUT_RING(obj->gtt_offset |
+			 MI_MM_SPACE_GTT |
+			 MI_SAVE_EXT_STATE_EN |
+			 MI_RESTORE_EXT_STATE_EN |
+			 MI_FORCE_RESTORE);
+		OUT_RING(MI_NOOP);
+		OUT_RING(MI_FLUSH);
+		ADVANCE_LP_RING();
+	}
 }
 
 void intel_disable_clock_gating(struct drm_device *dev)




More information about the Intel-gfx mailing list