drm/i915: Workaround to bump rc6 voltage to 450
authorBen Widawsky <ben@bwidawsk.net>
Wed, 26 Sep 2012 17:34:01 +0000 (10:34 -0700)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 16 Oct 2012 07:23:52 +0000 (09:23 +0200)
BIOS should be setting the minimum voltage for rc6 to be 450mV. Old or
buggy BIOSen may not be doing this, so we correct it for them. Ideally
customers should update the BIOS as only it would know the optimal
values for the platform, so we leave that fact as a DRM_ERROR for the
user to see.

Unfortunately this isn't fixing any of the issues it was targeted to
fix, but it is documented that we must do it.

CC: Jesse Barnes <jbarnes@virtuousgeek.org>
CC: Matt Turner <mattst88@gmail.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
[danvet: bikeshedded loglevel of the "your bios is broken message" to
debug.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_pm.c

index 8200c317f1fd74287eda0d6a878ede39f3def391..d7f516c4855a71bc33cc0535e305f6f56398fb06 100644 (file)
 #define   GEN6_READ_OC_PARAMS                  0xc
 #define   GEN6_PCODE_WRITE_MIN_FREQ_TABLE      0x8
 #define   GEN6_PCODE_READ_MIN_FREQ_TABLE       0x9
+#define          GEN6_PCODE_WRITE_RC6VIDS              0x4
+#define          GEN6_PCODE_READ_RC6VIDS               0x5
+#define   GEN6_ENCODE_RC6_VID(mv)              (((mv) / 5) - 245) < 0 ?: 0
+#define   GEN6_DECODE_RC6_VID(vids)            (((vids) * 5) > 0 ? ((vids) * 5) + 245 : 0)
 #define GEN6_PCODE_DATA                                0x138128
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT       8
 
index 0cc7dbf55bee3095617d8774e05ea15388a9fca1..a56ca428c38efea8013a79a5c2e349cb9ba95bd0 100644 (file)
@@ -2404,7 +2404,7 @@ static void gen6_enable_rps(struct drm_device *dev)
        struct intel_ring_buffer *ring;
        u32 rp_state_cap;
        u32 gt_perf_status;
-       u32 pcu_mbox, rc6_mask = 0;
+       u32 rc6vids, pcu_mbox, rc6_mask = 0;
        u32 gtfifodbg;
        int rc6_mode;
        int i, ret;
@@ -2526,6 +2526,20 @@ static void gen6_enable_rps(struct drm_device *dev)
        /* enable all PM interrupts */
        I915_WRITE(GEN6_PMINTRMSK, 0);
 
+       rc6vids = 0;
+       ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
+       if (IS_GEN6(dev) && ret) {
+               DRM_DEBUG_DRIVER("Couldn't check for BIOS workaround\n");
+       } else if (IS_GEN6(dev) && (GEN6_DECODE_RC6_VID(rc6vids & 0xff) < 450)) {
+               DRM_DEBUG_DRIVER("You should update your BIOS. Correcting minimum rc6 voltage (%dmV->%dmV)\n",
+                         GEN6_DECODE_RC6_VID(rc6vids & 0xff), 450);
+               rc6vids &= 0xffff00;
+               rc6vids |= GEN6_ENCODE_RC6_VID(450);
+               ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_RC6VIDS, rc6vids);
+               if (ret)
+                       DRM_ERROR("Couldn't fix incorrect rc6 voltage\n");
+       }
+
        gen6_gt_force_wake_put(dev_priv);
 }