drm/i915: make sure eDP PLL is enabled at the right time

We need to make sure the eDP PLL is enabled before the pipes or planes,
so do it as part of the DP prepare mode set function.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
Jesse Barnes 2010-08-13 15:43:26 -07:00
parent 9cce37f485
commit d240f20f54
2 changed files with 60 additions and 39 deletions

View File

@ -1622,32 +1622,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
return 0; return 0;
} }
static void ironlake_disable_pll_edp (struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpa_ctl;
DRM_DEBUG_KMS("\n");
dpa_ctl = I915_READ(DP_A);
dpa_ctl &= ~DP_PLL_ENABLE;
I915_WRITE(DP_A, dpa_ctl);
}
static void ironlake_enable_pll_edp (struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpa_ctl;
dpa_ctl = I915_READ(DP_A);
dpa_ctl |= DP_PLL_ENABLE;
I915_WRITE(DP_A, dpa_ctl);
POSTING_READ(DP_A);
udelay(200);
}
static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock) static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
@ -1940,10 +1914,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
} }
} }
if (HAS_eDP) { if (!HAS_eDP) {
/* enable eDP PLL */
ironlake_enable_pll_edp(crtc);
} else {
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */ /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
temp = I915_READ(fdi_rx_reg); temp = I915_READ(fdi_rx_reg);
@ -2242,10 +2213,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE); I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
I915_READ(pch_dpll_reg); I915_READ(pch_dpll_reg);
if (HAS_eDP) {
ironlake_disable_pll_edp(crtc);
}
/* Switch from PCDclk to Rawclk */ /* Switch from PCDclk to Rawclk */
temp = I915_READ(fdi_rx_reg); temp = I915_READ(fdi_rx_reg);
temp &= ~FDI_SEL_PCDCLK; temp &= ~FDI_SEL_PCDCLK;
@ -3930,9 +3897,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
dpll_reg = pch_dpll_reg; dpll_reg = pch_dpll_reg;
} }
if (is_edp) { if (!is_edp) {
ironlake_disable_pll_edp(crtc);
} else if ((dpll & DPLL_VCO_ENABLE)) {
I915_WRITE(fp_reg, fp); I915_WRITE(fp_reg, fp);
I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
I915_READ(dpll_reg); I915_READ(dpll_reg);

View File

@ -831,6 +831,60 @@ static void ironlake_edp_backlight_off (struct drm_device *dev)
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
} }
static void ironlake_edp_pll_on(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpa_ctl;
DRM_DEBUG_KMS("\n");
dpa_ctl = I915_READ(DP_A);
dpa_ctl &= ~DP_PLL_ENABLE;
I915_WRITE(DP_A, dpa_ctl);
}
static void ironlake_edp_pll_off(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpa_ctl;
dpa_ctl = I915_READ(DP_A);
dpa_ctl |= DP_PLL_ENABLE;
I915_WRITE(DP_A, dpa_ctl);
udelay(200);
}
static void intel_dp_prepare(struct drm_encoder *encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
if (IS_eDP(intel_dp)) {
ironlake_edp_backlight_off(dev);
ironlake_edp_panel_on(dev);
ironlake_edp_pll_on(encoder);
}
if (dp_reg & DP_PORT_EN)
intel_dp_link_down(intel_dp);
}
static void intel_dp_commit(struct drm_encoder *encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
if (!(dp_reg & DP_PORT_EN)) {
intel_dp_link_train(intel_dp);
}
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_backlight_on(dev);
}
static void static void
intel_dp_dpms(struct drm_encoder *encoder, int mode) intel_dp_dpms(struct drm_encoder *encoder, int mode)
{ {
@ -846,6 +900,8 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
} }
if (dp_reg & DP_PORT_EN) if (dp_reg & DP_PORT_EN)
intel_dp_link_down(intel_dp); intel_dp_link_down(intel_dp);
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_pll_off(encoder);
} else { } else {
if (!(dp_reg & DP_PORT_EN)) { if (!(dp_reg & DP_PORT_EN)) {
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
@ -1427,9 +1483,9 @@ intel_dp_destroy (struct drm_connector *connector)
static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
.dpms = intel_dp_dpms, .dpms = intel_dp_dpms,
.mode_fixup = intel_dp_mode_fixup, .mode_fixup = intel_dp_mode_fixup,
.prepare = intel_encoder_prepare, .prepare = intel_dp_prepare,
.mode_set = intel_dp_mode_set, .mode_set = intel_dp_mode_set,
.commit = intel_encoder_commit, .commit = intel_dp_commit,
}; };
static const struct drm_connector_funcs intel_dp_connector_funcs = { static const struct drm_connector_funcs intel_dp_connector_funcs = {