diff mbox

drm/i915: implement MCH pipe underrun prevention for snb/ivb

Message ID 1360247004-15707-1-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Vetter Feb. 7, 2013, 2:23 p.m. UTC
Some early bios versions seem to ship with the wrong tuning values for
the MCH, possible resulting in pipe underruns under load. Especially
on DP outputs this can lead to black screen, since DP really doesn't
like an occasional whack from an underrun.

Unfortunately the registers seem to be locked after boot, so the only
thing we can do is politely point out issues and suggest a BIOS
upgrade.

Arthur Runyan pointed us at this issue while discussion DP bugs - thus
far no confirmation from a bug report yet that it helps. But at least
some of my machines here have wrong values, so this might be useful in
understanding bug reports.

Cc: Runyan, Arthur J <arthur.j.runyan@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_reg.h |  8 ++++++++
 drivers/gpu/drm/i915/intel_pm.c | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

Comments

Ben Widawsky Feb. 7, 2013, 6:09 p.m. UTC | #1
On Thu, Feb 07, 2013 at 03:23:24PM +0100, Daniel Vetter wrote:
> Some early bios versions seem to ship with the wrong tuning values for
> the MCH, possible resulting in pipe underruns under load. Especially
> on DP outputs this can lead to black screen, since DP really doesn't
> like an occasional whack from an underrun.
> 
> Unfortunately the registers seem to be locked after boot, so the only
> thing we can do is politely point out issues and suggest a BIOS
> upgrade.
> 
> Arthur Runyan pointed us at this issue while discussion DP bugs - thus
> far no confirmation from a bug report yet that it helps. But at least
> some of my machines here have wrong values, so this might be useful in
> understanding bug reports.
> 
> Cc: Runyan, Arthur J <arthur.j.runyan@intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_reg.h |  8 ++++++++
>  drivers/gpu/drm/i915/intel_pm.c | 34 ++++++++++++++++++++++++++++++++++
>  2 files changed, 42 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 8754f91..b3915cf 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1235,6 +1235,14 @@
>  #define   MAD_DIMM_A_SIZE_SHIFT		0
>  #define   MAD_DIMM_A_SIZE_MASK		(0xff << MAD_DIMM_A_SIZE_SHIFT)
>  
> +/** snb MCH registers for priority tuning */
> +#define MCH_TC_RFP_C0			(MCHBAR_MIRROR_BASE_SNB + 0x4294)
> +#define MCH_TC_RFP_C1			(MCHBAR_MIRROR_BASE_SNB + 0x4694)
> +#define   TC_RFP_OREF_MASK		0xff
> +#define   TC_RFP_OREF_VAL		0xff
> +#define MCH_SSKPD			(MCHBAR_MIRROR_BASE_SNB + 0x5d10)
> +#define   MCH_SSKPD_WM0_MASK		0x3f
> +#define   MCH_SSKPD_WM0_VAL		0xc

According to the bug report I'm reading, there are several valid values,
so I think you should do some more work.

[snip]
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8754f91..b3915cf 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1235,6 +1235,14 @@ 
 #define   MAD_DIMM_A_SIZE_SHIFT		0
 #define   MAD_DIMM_A_SIZE_MASK		(0xff << MAD_DIMM_A_SIZE_SHIFT)
 
+/** snb MCH registers for priority tuning */
+#define MCH_TC_RFP_C0			(MCHBAR_MIRROR_BASE_SNB + 0x4294)
+#define MCH_TC_RFP_C1			(MCHBAR_MIRROR_BASE_SNB + 0x4694)
+#define   TC_RFP_OREF_MASK		0xff
+#define   TC_RFP_OREF_VAL		0xff
+#define MCH_SSKPD			(MCHBAR_MIRROR_BASE_SNB + 0x5d10)
+#define   MCH_SSKPD_WM0_MASK		0x3f
+#define   MCH_SSKPD_WM0_VAL		0xc
 
 /* Clocking configuration register */
 #define CLKCFG			0x10c00
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7c9a6d1..e4e6e87 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3584,6 +3584,36 @@  static void cpt_init_clock_gating(struct drm_device *dev)
 	}
 }
 
+static void gen6_check_mch_setup(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t tmp;
+	bool update_bios = false;
+
+	tmp = I915_READ(MCH_TC_RFP_C0);
+	if ((tmp & TC_RFP_OREF_MASK) != TC_RFP_OREF_VAL) {
+		DRM_INFO("Wrong MCH_TC_RFP_CO value: 0x%08x\n", tmp);
+		update_bios = true;
+	}
+
+	tmp = I915_READ(MCH_TC_RFP_C1);
+	if ((tmp & TC_RFP_OREF_MASK) != TC_RFP_OREF_VAL) {
+		DRM_INFO("Wrong MCH_TC_RFP_C1 value: 0x%08x\n", tmp);
+		update_bios = true;
+	}
+
+	tmp = I915_READ(MCH_SSKPD);
+	if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL) {
+		DRM_INFO("Wrong MCH_SSKPD value: 0x%08x\n", tmp);
+		update_bios = true;
+	}
+
+	if (update_bios) {
+		DRM_INFO("This can cause pipe underruns and display issues.\n");
+		DRM_INFO("Please upgrade your BIOS to fix this.\n");
+	}
+}
+
 static void gen6_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3676,6 +3706,8 @@  static void gen6_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI));
 
 	cpt_init_clock_gating(dev);
+
+	gen6_check_mch_setup(dev);
 }
 
 static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
@@ -3861,6 +3893,8 @@  static void ivybridge_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
 	cpt_init_clock_gating(dev);
+
+	gen6_check_mch_setup(dev);
 }
 
 static void valleyview_init_clock_gating(struct drm_device *dev)