[Intel-gfx] [RFC 02/30] drm/i915: disable DDI pipes and ports when initializing
Paulo Zanoni
przanoni at gmail.com
Wed Aug 29 00:06:33 CEST 2012
From: Paulo Zanoni <paulo.r.zanoni at intel.com>
This is required to prevent hanging the machine on Haswell. We need to
disable everything so when we start using we only enable/disable
exactly what we are using.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
---
drivers/gpu/drm/i915/i915_reg.h | 2 +
drivers/gpu/drm/i915/intel_ddi.c | 74 ++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_display.c | 7 ++--
drivers/gpu/drm/i915/intel_drv.h | 4 ++
drivers/gpu/drm/i915/intel_sprite.c | 6 +--
5 files changed, 86 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2eed9d4..ee70588 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4375,6 +4375,7 @@
#define PIPE_DDI_FUNC_ENABLE (1<<31)
/* Those bits are ignored by pipe EDP since it can only connect to DDI A */
#define PIPE_DDI_PORT_MASK (7<<28)
+#define PIPE_DDI_PORT_NONE (0<<28)
#define PIPE_DDI_SELECT_PORT(x) ((x)<<28)
#define PIPE_DDI_MODE_SELECT_MASK (7<<24)
#define PIPE_DDI_MODE_SELECT_HDMI (0<<24)
@@ -4503,6 +4504,7 @@
#define PORT_CLK_SEL_SPLL (3<<29)
#define PORT_CLK_SEL_WRPLL1 (4<<29)
#define PORT_CLK_SEL_WRPLL2 (5<<29)
+#define PORT_CLK_SEL_NONE (7<<29)
/* Pipe clock selection */
#define PIPE_CLK_SEL_A 0x46140
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 18ebf15..b8b7670 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -751,6 +751,20 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
intel_hdmi->set_infoframes(encoder, adjusted_mode);
}
+static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
+ enum port port)
+{
+ uint32_t reg = DDI_BUF_CTL(port);
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ udelay(1);
+ if (I915_READ(reg) & DDI_BUF_IS_IDLE)
+ return;
+ }
+ DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port));
+}
+
void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
@@ -775,11 +789,71 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
temp);
}
+static void intel_ddi_disable_pipe(struct drm_i915_private *dev_priv,
+ enum pipe pipe)
+{
+ uint32_t temp;
+
+ temp = I915_READ(DDI_FUNC_CTL(pipe));
+ temp &= ~(PIPE_DDI_FUNC_ENABLE | PIPE_DDI_PORT_MASK);
+ temp |= PIPE_DDI_PORT_NONE;
+ I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+
+ I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_DISABLED);
+}
+
+static void intel_ddi_disable_port(struct drm_i915_private *dev_priv,
+ enum port port)
+{
+ uint32_t reg, val;
+
+ reg = DDI_BUF_CTL(port);
+ val = I915_READ(reg);
+ if (val & DDI_BUF_CTL_ENABLE) {
+ val &= ~DDI_BUF_CTL_ENABLE;
+ I915_WRITE(reg, val);
+ intel_wait_ddi_buf_idle(dev_priv, port);
+ }
+
+ switch (I915_READ(PORT_CLK_SEL(port))) {
+ case PORT_CLK_SEL_WRPLL1:
+ reg = WRPLL_CTL1;
+ val = I915_READ(reg) & ~WRPLL_PLL_ENABLE;
+ break;
+ case PORT_CLK_SEL_WRPLL2:
+ reg = WRPLL_CTL2;
+ val = I915_READ(reg) & ~WRPLL_PLL_ENABLE;
+ break;
+ case PORT_CLK_SEL_SPLL:
+ reg = SPLL_CTL;
+ val = I915_READ(reg) & ~SPLL_PLL_ENABLE;
+ break;
+ default: /* LCPLL or none or reserved */
+ reg = 0;
+ }
+
+ if (reg)
+ I915_WRITE(reg, val);
+
+ I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+}
+
void intel_ddi_pll_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t lcpll_val, clk_val, temp;
bool lcpll_needs_change = false;
+ int i;
+
+ /* Reset all pipe clocks and ports so we don't hang the machine later */
+ for (i = PIPE_A; i <= PIPE_C; i++) {
+ intel_disable_plane(dev_priv, i, i);
+ intel_disable_pipe(dev_priv, i);
+ intel_ddi_disable_pipe(dev_priv, i);
+ }
+
+ for (i = PORT_A; i <= PORT_E; i++)
+ intel_ddi_disable_port(dev_priv, i);
/* Check the LCPLL state and fix it if needed. */
lcpll_val = I915_READ(LCPLL_CTL);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 11687d2..33eebcb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1773,8 +1773,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
*
* Will wait until the pipe has shut down before returning.
*/
-static void intel_disable_pipe(struct drm_i915_private *dev_priv,
- enum pipe pipe)
+void intel_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
{
int reg;
u32 val;
@@ -1844,8 +1843,8 @@ static void intel_enable_plane(struct drm_i915_private *dev_priv,
*
* Disable @plane; should be an independent operation.
*/
-static void intel_disable_plane(struct drm_i915_private *dev_priv,
- enum plane plane, enum pipe pipe)
+void intel_disable_plane(struct drm_i915_private *dev_priv,
+ enum plane plane, enum pipe pipe)
{
int reg;
u32 val;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cf9a1ad..2578158 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -390,6 +390,10 @@ extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
enum plane plane);
+extern void intel_disable_plane(struct drm_i915_private *dev_priv,
+ enum plane plane, enum pipe pipe);
+extern void intel_disable_pipe(struct drm_i915_private *dev_priv,
+ enum pipe pipe);
/* intel_panel.c */
extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index cc8df4d..4737303 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -531,7 +531,7 @@ out:
}
static int
-intel_disable_plane(struct drm_plane *plane)
+intel_disable_drm_plane(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -556,7 +556,7 @@ out:
static void intel_destroy_plane(struct drm_plane *plane)
{
struct intel_plane *intel_plane = to_intel_plane(plane);
- intel_disable_plane(plane);
+ intel_disable_drm_plane(plane);
drm_plane_cleanup(plane);
kfree(intel_plane);
}
@@ -625,7 +625,7 @@ out_unlock:
static const struct drm_plane_funcs intel_plane_funcs = {
.update_plane = intel_update_plane,
- .disable_plane = intel_disable_plane,
+ .disable_plane = intel_disable_drm_plane,
.destroy = intel_destroy_plane,
};
--
1.7.11.2
More information about the Intel-gfx
mailing list