| From 4999e50705bba978fee82b49a5e8fd11913fa118 Mon Sep 17 00:00:00 2001 |
| From: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Date: Fri, 7 Jun 2013 23:10:03 +0200 |
| Subject: drm/i915: switch crtc->shared_dpll from a pointer to an enum |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| Dealing with discrete enum values is simpler for hw state readout and |
| pipe config computations than pointers - having neat names instead of |
| chasing pointers should look better in the code. |
| |
| This isn't a that good reason for pch plls, but on haswell we actually |
| have 3 different types of plls: WRPLL, SPLL and the DP clocks. Having |
| explicit names should help there. |
| |
| Since this also adds the intel_crtc_to_shared_dpll helper to further |
| abstract away the crtc -> dpll relationship this will also help to |
| make the next patch simpler, which moves the shared dpll into the pipe |
| configuration. |
| |
| Also note that for uniformity we have two special dpll ids: NONE for |
| pipes which need a shared pll but don't have one (yet) and private for |
| when there's a non-shared pll (e.g. per-pipe or per-port pll). |
| |
| I've thought whether we should also add a 2nd enum for the type of the |
| pll we want (for really generic pll selection code) but thrown that |
| idea out again - likely there's too much platform craziness going on |
| to be able to share the pll selection logic much. |
| |
| Since this touched all the shared_pll functions a bit I've also done |
| an s/intel_crtc/crtc/ replacement on a few of them. |
| |
| v2: Kill DPLL_ID_NONE. It's probably better to call it DPLL_ID_INVALID and use |
| it to check that the compute config stage assigns a dpll to every pipe. |
| But since that code isn't ready yet until we move the dpll selection out |
| of the ->mode_set callback, there's no use for it. |
| |
| Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> |
| Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| (cherry picked from commit e2b78267421c2b407409772119a4aa500da56cc8) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/i915_drv.h | 7 +++ |
| drivers/gpu/drm/i915/intel_display.c | 90 ++++++++++++++++++++---------------- |
| drivers/gpu/drm/i915/intel_drv.h | 2 +- |
| 3 files changed, 58 insertions(+), 41 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h |
| index d46339018156..81a424d91c20 100644 |
| --- a/drivers/gpu/drm/i915/i915_drv.h |
| +++ b/drivers/gpu/drm/i915/i915_drv.h |
| @@ -140,6 +140,13 @@ struct intel_shared_dpll { |
| int fp0_reg; |
| int fp1_reg; |
| }; |
| + |
| +enum intel_dpll_id { |
| + DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */ |
| + /* real shared dpll ids must be >= 0 */ |
| + DPLL_ID_PCH_PLL_A, |
| + DPLL_ID_PCH_PLL_B, |
| +}; |
| #define I915_NUM_PLLS 2 |
| |
| /* Used by dp and fdi links */ |
| diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c |
| index 2f2f68a9a6d3..9af8a7449d3f 100644 |
| --- a/drivers/gpu/drm/i915/intel_display.c |
| +++ b/drivers/gpu/drm/i915/intel_display.c |
| @@ -909,6 +909,17 @@ static void assert_pll(struct drm_i915_private *dev_priv, |
| #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 * |
| +intel_crtc_to_shared_dpll(struct intel_crtc *crtc) |
| +{ |
| + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; |
| + |
| + if (crtc->shared_dpll < 0) |
| + return NULL; |
| + |
| + return &dev_priv->shared_dplls[crtc->shared_dpll]; |
| +} |
| + |
| /* For ILK+ */ |
| static void assert_shared_dpll(struct drm_i915_private *dev_priv, |
| struct intel_shared_dpll *pll, |
| @@ -1404,16 +1415,15 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port) |
| * The PCH PLL needs to be enabled before the PCH transcoder, since it |
| * drives the transcoder clock. |
| */ |
| -static void ironlake_enable_shared_dpll(struct intel_crtc *intel_crtc) |
| +static void ironlake_enable_shared_dpll(struct intel_crtc *crtc) |
| { |
| - struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; |
| - struct intel_shared_dpll *pll; |
| + 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); |
| - pll = intel_crtc->shared_dpll; |
| if (pll == NULL) |
| return; |
| |
| @@ -1422,7 +1432,7 @@ static void ironlake_enable_shared_dpll(struct intel_crtc *intel_crtc) |
| |
| DRM_DEBUG_KMS("enable PCH PLL %x (active %d, on? %d)for crtc %d\n", |
| pll->pll_reg, pll->active, pll->on, |
| - intel_crtc->base.base.id); |
| + crtc->base.base.id); |
| |
| /* PCH refclock must be enabled first */ |
| assert_pch_refclk_enabled(dev_priv); |
| @@ -1446,10 +1456,10 @@ static void ironlake_enable_shared_dpll(struct intel_crtc *intel_crtc) |
| pll->on = true; |
| } |
| |
| -static void intel_disable_shared_dpll(struct intel_crtc *intel_crtc) |
| +static void intel_disable_shared_dpll(struct intel_crtc *crtc) |
| { |
| - struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; |
| - struct intel_shared_dpll *pll = intel_crtc->shared_dpll; |
| + 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; |
| |
| @@ -1463,7 +1473,7 @@ static void intel_disable_shared_dpll(struct intel_crtc *intel_crtc) |
| |
| DRM_DEBUG_KMS("disable PCH PLL %x (active %d, on? %d) for crtc %d\n", |
| pll->pll_reg, pll->active, pll->on, |
| - intel_crtc->base.base.id); |
| + crtc->base.base.id); |
| |
| if (WARN_ON(pll->active == 0)) { |
| assert_shared_dpll_disabled(dev_priv, pll, NULL); |
| @@ -1478,7 +1488,7 @@ static void intel_disable_shared_dpll(struct intel_crtc *intel_crtc) |
| DRM_DEBUG_KMS("disabling PCH PLL %x\n", pll->pll_reg); |
| |
| /* Make sure transcoder isn't still depending on us */ |
| - assert_pch_transcoder_disabled(dev_priv, intel_crtc->pipe); |
| + assert_pch_transcoder_disabled(dev_priv, crtc->pipe); |
| |
| reg = pll->pll_reg; |
| val = I915_READ(reg); |
| @@ -1495,6 +1505,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, |
| { |
| struct drm_device *dev = dev_priv->dev; |
| struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; |
| + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| uint32_t reg, val, pipeconf_val; |
| |
| /* PCH only available on ILK+ */ |
| @@ -1502,8 +1513,8 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, |
| |
| /* Make sure PCH DPLL is enabled */ |
| assert_shared_dpll_enabled(dev_priv, |
| - to_intel_crtc(crtc)->shared_dpll, |
| - to_intel_crtc(crtc)); |
| + intel_crtc_to_shared_dpll(intel_crtc), |
| + intel_crtc); |
| |
| /* FDI must be feeding us bits for PCH ports */ |
| assert_fdi_tx_enabled(dev_priv, pipe); |
| @@ -2990,7 +3001,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) |
| sel = TRANSC_DPLLB_SEL; |
| break; |
| } |
| - if (intel_crtc->shared_dpll->pll_reg == _PCH_DPLL_B) |
| + if (intel_crtc->shared_dpll == DPLL_ID_PCH_PLL_B) |
| temp |= sel; |
| else |
| temp &= ~sel; |
| @@ -3059,9 +3070,9 @@ static void lpt_pch_enable(struct drm_crtc *crtc) |
| lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); |
| } |
| |
| -static void intel_put_shared_dpll(struct intel_crtc *intel_crtc) |
| +static void intel_put_shared_dpll(struct intel_crtc *crtc) |
| { |
| - struct intel_shared_dpll *pll = intel_crtc->shared_dpll; |
| + struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); |
| |
| if (pll == NULL) |
| return; |
| @@ -3076,29 +3087,28 @@ static void intel_put_shared_dpll(struct intel_crtc *intel_crtc) |
| WARN_ON(pll->active); |
| } |
| |
| - intel_crtc->shared_dpll = NULL; |
| + crtc->shared_dpll = DPLL_ID_PRIVATE; |
| } |
| |
| -static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *intel_crtc, u32 dpll, u32 fp) |
| +static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, u32 dpll, u32 fp) |
| { |
| - struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; |
| - struct intel_shared_dpll *pll; |
| - int i; |
| + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; |
| + struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); |
| + enum intel_dpll_id i; |
| |
| - pll = intel_crtc->shared_dpll; |
| if (pll) { |
| DRM_DEBUG_KMS("CRTC:%d dropping existing PCH PLL %x\n", |
| - intel_crtc->base.base.id, pll->pll_reg); |
| - intel_put_shared_dpll(intel_crtc); |
| + crtc->base.base.id, pll->pll_reg); |
| + intel_put_shared_dpll(crtc); |
| } |
| |
| if (HAS_PCH_IBX(dev_priv->dev)) { |
| /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ |
| - i = intel_crtc->pipe; |
| + i = crtc->pipe; |
| pll = &dev_priv->shared_dplls[i]; |
| |
| DRM_DEBUG_KMS("CRTC:%d using pre-allocated PCH PLL %x\n", |
| - intel_crtc->base.base.id, pll->pll_reg); |
| + crtc->base.base.id, pll->pll_reg); |
| |
| goto found; |
| } |
| @@ -3113,7 +3123,7 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *intel_ |
| if (dpll == (I915_READ(pll->pll_reg) & 0x7fffffff) && |
| fp == I915_READ(pll->fp0_reg)) { |
| DRM_DEBUG_KMS("CRTC:%d sharing existing PCH PLL %x (refcount %d, ative %d)\n", |
| - intel_crtc->base.base.id, |
| + crtc->base.base.id, |
| pll->pll_reg, pll->refcount, pll->active); |
| |
| goto found; |
| @@ -3125,7 +3135,7 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *intel_ |
| pll = &dev_priv->shared_dplls[i]; |
| if (pll->refcount == 0) { |
| DRM_DEBUG_KMS("CRTC:%d allocated PCH PLL %x\n", |
| - intel_crtc->base.base.id, pll->pll_reg); |
| + crtc->base.base.id, pll->pll_reg); |
| goto found; |
| } |
| } |
| @@ -3133,8 +3143,8 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *intel_ |
| return NULL; |
| |
| found: |
| - intel_crtc->shared_dpll = pll; |
| - DRM_DEBUG_DRIVER("using pll %d for pipe %c\n", i, pipe_name(intel_crtc->pipe)); |
| + crtc->shared_dpll = i; |
| + DRM_DEBUG_DRIVER("using pll %d for pipe %c\n", i, pipe_name(crtc->pipe)); |
| if (pll->active == 0) { |
| DRM_DEBUG_DRIVER("setting up pll %d\n", i); |
| WARN_ON(pll->on); |
| @@ -5730,6 +5740,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, |
| bool ok, has_reduced_clock = false; |
| bool is_lvds = false; |
| struct intel_encoder *encoder; |
| + struct intel_shared_dpll *pll; |
| int ret; |
| |
| for_each_encoder_on_crtc(dev, crtc, encoder) { |
| @@ -5765,8 +5776,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, |
| |
| /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ |
| if (intel_crtc->config.has_pch_encoder) { |
| - struct intel_shared_dpll *pll; |
| - |
| fp = i9xx_dpll_compute_fp(&intel_crtc->config.dpll); |
| if (has_reduced_clock) |
| fp2 = i9xx_dpll_compute_fp(&reduced_clock); |
| @@ -5791,11 +5800,15 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, |
| if (encoder->pre_pll_enable) |
| encoder->pre_pll_enable(encoder); |
| |
| - if (intel_crtc->shared_dpll) { |
| - I915_WRITE(intel_crtc->shared_dpll->pll_reg, dpll); |
| + intel_crtc->lowfreq_avail = false; |
| + |
| + if (intel_crtc->config.has_pch_encoder) { |
| + pll = intel_crtc_to_shared_dpll(intel_crtc); |
| + |
| + I915_WRITE(pll->pll_reg, dpll); |
| |
| /* Wait for the clocks to stabilize. */ |
| - POSTING_READ(intel_crtc->shared_dpll->pll_reg); |
| + POSTING_READ(pll->pll_reg); |
| udelay(150); |
| |
| /* The pixel multiplier can only be updated once the |
| @@ -5803,16 +5816,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, |
| * |
| * So write it again. |
| */ |
| - I915_WRITE(intel_crtc->shared_dpll->pll_reg, dpll); |
| - } |
| + I915_WRITE(pll->pll_reg, dpll); |
| |
| - intel_crtc->lowfreq_avail = false; |
| - if (intel_crtc->shared_dpll) { |
| if (is_lvds && has_reduced_clock && i915_powersave) { |
| - I915_WRITE(intel_crtc->shared_dpll->fp1_reg, fp2); |
| + I915_WRITE(pll->fp1_reg, fp2); |
| intel_crtc->lowfreq_avail = true; |
| } else { |
| - I915_WRITE(intel_crtc->shared_dpll->fp1_reg, fp); |
| + I915_WRITE(pll->fp1_reg, fp); |
| } |
| } |
| |
| diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h |
| index ccf92ff03755..bcc313368410 100644 |
| --- a/drivers/gpu/drm/i915/intel_drv.h |
| +++ b/drivers/gpu/drm/i915/intel_drv.h |
| @@ -317,7 +317,7 @@ struct intel_crtc { |
| struct intel_crtc_config config; |
| |
| /* We can share PLLs across outputs if the timings match */ |
| - struct intel_shared_dpll *shared_dpll; |
| + enum intel_dpll_id shared_dpll; |
| uint32_t ddi_pll_sel; |
| |
| /* reset counter value when the last flip was submitted */ |
| -- |
| 1.8.5.rc3 |
| |