Commit 55607e8a authored by Daniel Vetter's avatar Daniel Vetter

drm/i915: asserts for lvds pre_enable

Lots of bangin my head against the wall^UExperiments have shown that
we really need to enable the lvds port before we enable plls. Strangely
that seems to include the fdi rx pll on the pch.

Note that the pch pll assert can fire since the lvds port has it's own
special clock source settings in the DPLL register, which means it
will never have a shared dpll (since there's only one LVDS port).

Anyway, encode this new evidence with a few nice WARNs.

v2: Incorporate review comments from Imre.
- Explain why lvds can't have a shared dpll.
- Update the WARN output.

Cc: Imre Deak <imre.deak@intel.com>
Reviewed-by: default avatarImre Deak <imre.deak@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 87442f73
...@@ -892,7 +892,7 @@ static const char *state_string(bool enabled) ...@@ -892,7 +892,7 @@ static const char *state_string(bool enabled)
} }
/* Only for pre-ILK configs */ /* Only for pre-ILK configs */
static void assert_pll(struct drm_i915_private *dev_priv, void assert_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state) enum pipe pipe, bool state)
{ {
int reg; int reg;
...@@ -906,10 +906,8 @@ static void assert_pll(struct drm_i915_private *dev_priv, ...@@ -906,10 +906,8 @@ static void assert_pll(struct drm_i915_private *dev_priv,
"PLL state assertion failure (expected %s, current %s)\n", "PLL state assertion failure (expected %s, current %s)\n",
state_string(state), state_string(cur_state)); state_string(state), state_string(cur_state));
} }
#define assert_pll_enabled(d, p) assert_pll(d, p, true)
#define assert_pll_disabled(d, p) assert_pll(d, p, false)
static struct intel_shared_dpll * struct intel_shared_dpll *
intel_crtc_to_shared_dpll(struct intel_crtc *crtc) intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
{ {
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
...@@ -921,7 +919,7 @@ intel_crtc_to_shared_dpll(struct intel_crtc *crtc) ...@@ -921,7 +919,7 @@ intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
} }
/* For ILK+ */ /* For ILK+ */
static void assert_shared_dpll(struct drm_i915_private *dev_priv, void assert_shared_dpll(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll, struct intel_shared_dpll *pll,
bool state) bool state)
{ {
...@@ -942,8 +940,6 @@ static void assert_shared_dpll(struct drm_i915_private *dev_priv, ...@@ -942,8 +940,6 @@ static void assert_shared_dpll(struct drm_i915_private *dev_priv,
"%s assertion failure (expected %s, current %s)\n", "%s assertion failure (expected %s, current %s)\n",
pll->name, state_string(state), state_string(cur_state)); pll->name, state_string(state), state_string(cur_state));
} }
#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
static void assert_fdi_tx(struct drm_i915_private *dev_priv, static void assert_fdi_tx(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state) enum pipe pipe, bool state)
...@@ -1007,15 +1003,19 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv, ...@@ -1007,15 +1003,19 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n"); WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n");
} }
static void assert_fdi_rx_pll_enabled(struct drm_i915_private *dev_priv, void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
enum pipe pipe) enum pipe pipe, bool state)
{ {
int reg; int reg;
u32 val; u32 val;
bool cur_state;
reg = FDI_RX_CTL(pipe); reg = FDI_RX_CTL(pipe);
val = I915_READ(reg); val = I915_READ(reg);
WARN(!(val & FDI_RX_PLL_ENABLE), "FDI RX PLL assertion failure, should be active but is disabled\n"); cur_state = !!(val & FDI_RX_PLL_ENABLE);
WARN(cur_state != state,
"FDI RX PLL assertion failure (expected %s, current %s)\n",
state_string(state), state_string(cur_state));
} }
static void assert_panel_unlocked(struct drm_i915_private *dev_priv, static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
......
...@@ -747,6 +747,22 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data, ...@@ -747,6 +747,22 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data,
extern void intel_fb_output_poll_changed(struct drm_device *dev); extern void intel_fb_output_poll_changed(struct drm_device *dev);
extern void intel_fb_restore_mode(struct drm_device *dev); extern void intel_fb_restore_mode(struct drm_device *dev);
struct intel_shared_dpll *
intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
void assert_shared_dpll(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
bool state);
#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
void assert_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state);
#define assert_pll_enabled(d, p) assert_pll(d, p, true)
#define assert_pll_disabled(d, p) assert_pll(d, p, false)
void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state);
#define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true)
#define assert_fdi_rx_pll_disabled(d, p) assert_fdi_rx_pll(d, p, false)
extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
bool state); bool state);
#define assert_pipe_enabled(d, p) assert_pipe(d, p, true) #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
......
...@@ -120,12 +120,20 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder) ...@@ -120,12 +120,20 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
struct drm_display_mode *fixed_mode = struct drm_display_mode *fixed_mode =
lvds_encoder->attached_connector->base.panel.fixed_mode; lvds_encoder->attached_connector->base.panel.fixed_mode;
int pipe = intel_crtc->pipe; int pipe = crtc->pipe;
u32 temp; u32 temp;
if (HAS_PCH_SPLIT(dev)) {
assert_fdi_rx_pll_disabled(dev_priv, pipe);
assert_shared_dpll_disabled(dev_priv,
intel_crtc_to_shared_dpll(crtc));
} else {
assert_pll_disabled(dev_priv, pipe);
}
temp = I915_READ(lvds_encoder->reg); temp = I915_READ(lvds_encoder->reg);
temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
...@@ -142,7 +150,7 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder) ...@@ -142,7 +150,7 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
/* set the corresponsding LVDS_BORDER bit */ /* set the corresponsding LVDS_BORDER bit */
temp &= ~LVDS_BORDER_ENABLE; temp &= ~LVDS_BORDER_ENABLE;
temp |= intel_crtc->config.gmch_pfit.lvds_border_bits; temp |= crtc->config.gmch_pfit.lvds_border_bits;
/* Set the B0-B3 data pairs corresponding to whether we're going to /* Set the B0-B3 data pairs corresponding to whether we're going to
* set the DPLLs for dual-channel mode or not. * set the DPLLs for dual-channel mode or not.
*/ */
...@@ -162,8 +170,7 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder) ...@@ -162,8 +170,7 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
if (INTEL_INFO(dev)->gen == 4) { if (INTEL_INFO(dev)->gen == 4) {
/* Bspec wording suggests that LVDS port dithering only exists /* Bspec wording suggests that LVDS port dithering only exists
* for 18bpp panels. */ * for 18bpp panels. */
if (intel_crtc->config.dither && if (crtc->config.dither && crtc->config.pipe_bpp == 18)
intel_crtc->config.pipe_bpp == 18)
temp |= LVDS_ENABLE_DITHER; temp |= LVDS_ENABLE_DITHER;
else else
temp &= ~LVDS_ENABLE_DITHER; temp &= ~LVDS_ENABLE_DITHER;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment