Looks at first like a bit of overkill, but - Haswell actually wants different enable/disable functions for different plls. - And once we have full dpll hw state tracking we can move the full register setup into the ->enable hook. Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch> --- drivers/gpu/drm/i915/i915_drv.h | 7 +++- drivers/gpu/drm/i915/intel_display.c | 71 ++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index df3d0f3..8e61128 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -132,6 +132,8 @@ enum hpd_pin { list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ if ((intel_encoder)->base.crtc == (__crtc)) +struct drm_i915_private; + enum intel_dpll_id { DPLL_ID_NONE = -2, /* no dpll assigned/used */ DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */ @@ -148,6 +150,10 @@ struct intel_shared_dpll { const char *name; /* should match the index in the dev_priv->shared_dplls array */ enum intel_dpll_id id; + void (*enable)(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll); + void (*disable)(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll); }; /* Used by dp and fdi links */ @@ -203,7 +209,6 @@ struct opregion_header; struct opregion_acpi; struct opregion_swsci; struct opregion_asle; -struct drm_i915_private; struct intel_opregion { struct opregion_header __iomem *header; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f2c0d79..1c4aedd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1389,8 +1389,6 @@ static void ironlake_enable_shared_dpll(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); - int reg; - u32 val; /* PCH PLLs only available on ILK, SNB and IVB */ BUG_ON(dev_priv->info->gen < 5); @@ -1404,9 +1402,6 @@ static void ironlake_enable_shared_dpll(struct intel_crtc *crtc) pll->name, pll->active, pll->on, crtc->base.base.id); - /* PCH refclock must be enabled first */ - assert_pch_refclk_enabled(dev_priv); - if (pll->active++) { WARN_ON(!pll->on); assert_shared_dpll_enabled(dev_priv, pll, NULL); @@ -1414,14 +1409,7 @@ static void ironlake_enable_shared_dpll(struct intel_crtc *crtc) } DRM_DEBUG_KMS("enabling %s\n", pll->name); - - reg = PCH_DPLL(pll->id); - val = I915_READ(reg); - val |= DPLL_VCO_ENABLE; - I915_WRITE(reg, val); - POSTING_READ(reg); - udelay(200); - + pll->enable(dev_priv, pll); pll->on = true; } @@ -1429,8 +1417,6 @@ static void intel_disable_shared_dpll(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); - int reg; - u32 val; /* PCH only available on ILK+ */ BUG_ON(dev_priv->info->gen < 5); @@ -1455,17 +1441,7 @@ static void intel_disable_shared_dpll(struct intel_crtc *crtc) return; DRM_DEBUG_KMS("disabling %s\n", pll->name); - - /* Make sure transcoder isn't still depending on us */ - assert_pch_transcoder_disabled(dev_priv, crtc->pipe); - - reg = PCH_DPLL(pll->id); - val = I915_READ(reg); - val &= ~DPLL_VCO_ENABLE; - I915_WRITE(reg, val); - POSTING_READ(reg); - udelay(200); - + pll->disable(dev_priv, pll); pll->on = false; } @@ -8666,6 +8642,43 @@ static void intel_cpu_pll_init(struct drm_device *dev) intel_ddi_pll_init(dev); } +static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + uint32_t reg, val; + + /* PCH refclock must be enabled first */ + assert_pch_refclk_enabled(dev_priv); + + reg = PCH_DPLL(pll->id); + val = I915_READ(reg); + val |= DPLL_VCO_ENABLE; + I915_WRITE(reg, val); + POSTING_READ(reg); + udelay(200); +} + +static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + struct drm_device *dev = dev_priv->dev; + struct intel_crtc *crtc; + uint32_t reg, val; + + /* Make sure no transcoder isn't still depending on us. */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + if (intel_crtc_to_shared_dpll(crtc) == pll) + assert_pch_transcoder_disabled(dev_priv, crtc->pipe); + } + + reg = PCH_DPLL(pll->id); + val = I915_READ(reg); + val &= ~DPLL_VCO_ENABLE; + I915_WRITE(reg, val); + POSTING_READ(reg); + udelay(200); +} + static char *ibx_pch_dpll_names[] = { "PCH DPLL A", "PCH DPLL B", @@ -8673,7 +8686,7 @@ static char *ibx_pch_dpll_names[] = { static void ibx_pch_dpll_init(struct drm_device *dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; int i; dev_priv->num_shared_dpll = 2; @@ -8681,12 +8694,14 @@ static void ibx_pch_dpll_init(struct drm_device *dev) for (i = 0; i < dev_priv->num_shared_dpll; i++) { dev_priv->shared_dplls[i].id = i; dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i]; + dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable; + dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable; } } static void intel_shared_dpll_init(struct drm_device *dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { ibx_pch_dpll_init(dev); -- 1.7.11.7