diff mbox

drm/i915/bxt: Fix DSI HW state readout

Message ID 1458767983-6473-1-git-send-email-imre.deak@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Imre Deak March 23, 2016, 9:19 p.m. UTC
Currently the machine hangs during booting while accessing the
BXT_MIPI_PORT_CTRL register during pipe HW state readout. After some
experimentation I found that the hang is caused by the DSI PLL being
disabled, or it being enabled but with an incorrect divider
configuration. Enabling the PLL got rid of the boot problem, so fix
this by checking the PLL enabled state/configuration before attempting
to read out the HW state.

Ville also found this dependency specified in BSpec, so I added a
reference to that too.

CC: Shashank Sharma <shashank.sharma@intel.com>
CC: Uma Shankar <uma.shankar@intel.com>
CC: Jani Nikula <jani.nikula@intel.com>
Fixes: c6c794a2fc5e ("drm/i915/bxt: Initialize MIPI DSI for BXT")
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |  2 ++
 drivers/gpu/drm/i915/intel_display.c |  9 +++++++++
 drivers/gpu/drm/i915/intel_dsi.c     |  8 ++++++++
 drivers/gpu/drm/i915/intel_dsi.h     |  1 +
 drivers/gpu/drm/i915/intel_dsi_pll.c | 37 ++++++++++++++++++++++++++++++++++++
 5 files changed, 57 insertions(+)

Comments

Imre Deak March 24, 2016, 12:50 p.m. UTC | #1
On to, 2016-03-24 at 11:32 +0000, Patchwork wrote:
> == Series Details ==
> 
> Series: drm/i915/bxt: Fix DSI HW state readout (rev3)
> URL   : https://patchwork.freedesktop.org/series/4832/
> State : success
> 
> == Summary ==
> 
> Series 4832v3 drm/i915/bxt: Fix DSI HW state readout
> http://patchwork.freedesktop.org/api/1.0/series/4832/revisions/3/mbox
> /
> 
> Test gem_exec_suspend:
>         Subgroup basic-s3:
>                 dmesg-warn -> PASS       (bsw-nuc-2)
> Test kms_pipe_crc_basic:
>         Subgroup suspend-read-crc-pipe-c:
>                 incomplete -> PASS       (hsw-gt2)

Thanks for the review, I pushed the patch to -dinq.

--Imre

> bdw-
> nuci7        total:192  pass:180  dwarn:0   dfail:0   fail:0   skip:1
> 2 
> bdw-
> ultra        total:192  pass:171  dwarn:0   dfail:0   fail:0   skip:2
> 1 
> bsw-nuc-
> 2        total:192  pass:155  dwarn:0   dfail:0   fail:0   skip:37 
> byt-
> nuc          total:192  pass:156  dwarn:1   dfail:0   fail:0   skip:3
> 5 
> hsw-
> brixbox      total:192  pass:170  dwarn:0   dfail:0   fail:0   skip:2
> 2 
> hsw-
> gt2          total:192  pass:175  dwarn:0   dfail:0   fail:0   skip:1
> 7 
> ivb-
> t430s        total:192  pass:167  dwarn:0   dfail:0   fail:0   skip:2
> 5 
> skl-i7k-
> 2        total:192  pass:169  dwarn:0   dfail:0   fail:0   skip:23 
> skl-
> nuci5        total:192  pass:181  dwarn:0   dfail:0   fail:0   skip:1
> 1 
> snb-
> dellxps      total:192  pass:158  dwarn:0   dfail:0   fail:0   skip:3
> 4 
> snb-
> x220t        total:192  pass:158  dwarn:0   dfail:0   fail:1   skip:3
> 3 
> 
> Results at /archive/results/CI_IGT_test/Patchwork_1703/
> 
> 79ee42317266a82b932a39e9567244ed91dd27d6 drm-intel-nightly: 2016y-
> 03m-24d-10h-26m-54s UTC integration manifest
> 8e94bd5898ec48db5dcfed6dbbe1cf1e9ac2499f drm/i915/bxt: Fix DSI HW
> state readout
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f3ba43c..c839ce9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -7811,9 +7811,11 @@  enum skl_disp_power_wells {
 #define  BXT_DSIC_16X_BY2		(1 << 10)
 #define  BXT_DSIC_16X_BY3		(2 << 10)
 #define  BXT_DSIC_16X_BY4		(3 << 10)
+#define  BXT_DSIC_16X_MASK		(3 << 10)
 #define  BXT_DSIA_16X_BY2		(1 << 8)
 #define  BXT_DSIA_16X_BY3		(2 << 8)
 #define  BXT_DSIA_16X_BY4		(3 << 8)
+#define  BXT_DSIA_16X_MASK		(3 << 8)
 #define  BXT_DSI_FREQ_SEL_SHIFT		8
 #define  BXT_DSI_FREQ_SEL_MASK		(0xF << BXT_DSI_FREQ_SEL_SHIFT)
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 009b03b..d5dc6b3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -36,6 +36,7 @@ 
 #include "intel_drv.h"
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
+#include "intel_dsi.h"
 #include "i915_trace.h"
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -9856,6 +9857,14 @@  static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
 
 	pipe_config->has_dsi_encoder = false;
 
+	/*
+	 * The PLL needs to be enabled with a valid divider configuration,
+	 * otherwise accessing DSI registers will hang the machine.
+	 * See BSpec North Display Engine registers/MIPI[BXT].
+	 */
+	if (!intel_dsi_pll_is_enabled(dev_priv))
+		return false;
+
 	for_each_port_masked(port, BIT(PORT_A) | BIT(PORT_C)) {
 		if (port == PORT_A)
 			cpu_transcoder = TRANSCODER_DSI_A;
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 96ea3f7..656807f 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -680,6 +680,14 @@  static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
 
 	DRM_DEBUG_KMS("\n");
 
+	/*
+	 * On Broxton the PLL needs to be enabled with a valid divider
+	 * configuration, otherwise accessing DSI registers will hang the
+	 * machine. See BSpec North Display Engine registers/MIPI[BXT].
+	 */
+	if (IS_BROXTON(dev_priv) && !intel_dsi_pll_is_enabled(dev_priv))
+		return false;
+
 	power_domain = intel_display_port_power_domain(encoder);
 	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
 		return false;
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index e582ef8..ec58ead 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -126,6 +126,7 @@  static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
 	return container_of(encoder, struct intel_dsi, base.base);
 }
 
+bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv);
 extern void intel_enable_dsi_pll(struct intel_encoder *encoder);
 extern void intel_disable_dsi_pll(struct intel_encoder *encoder);
 extern u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp);
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index e3e343c..e5b0625 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -192,6 +192,33 @@  static void vlv_disable_dsi_pll(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
+static bool bxt_dsi_pll_is_enabled(struct drm_i915_private *dev_priv)
+{
+	bool enabled;
+	u32 val;
+	u32 mask;
+
+	mask = BXT_DSI_PLL_DO_ENABLE | BXT_DSI_PLL_LOCKED;
+	val = I915_READ(BXT_DSI_PLL_ENABLE);
+	enabled = (val & mask) == mask;
+
+	if (!enabled)
+		return false;
+
+	/*
+	 * Both dividers must be programmed with valid values even if only one
+	 * of the PLL is used. See BSpec/Broxton Clocks.
+	 */
+	val = I915_READ(BXT_DSI_PLL_CTL);
+	if (!(val & BXT_DSIA_16X_MASK) || !(val & BXT_DSIC_16X_MASK)) {
+		DRM_DEBUG_DRIVER("PLL is enabled with invalid divider settings "
+				 "(%08x)\n", val);
+		enabled = false;
+	}
+
+	return enabled;
+}
+
 static void bxt_disable_dsi_pll(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -486,6 +513,16 @@  static void bxt_enable_dsi_pll(struct intel_encoder *encoder)
 	DRM_DEBUG_KMS("DSI PLL locked\n");
 }
 
+bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv)
+{
+	if (IS_BROXTON(dev_priv))
+		return bxt_dsi_pll_is_enabled(dev_priv);
+
+	MISSING_CASE(INTEL_DEVID(dev_priv));
+
+	return false;
+}
+
 void intel_enable_dsi_pll(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;