drm/i915: hw state readout for shared pch plls
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 7 Jun 2013 21:11:08 +0000 (23:11 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 10 Jun 2013 17:49:14 +0000 (19:49 +0200)
Well, the first step of a long road at least, it only reads out
the pipe -> shared dpll association thus far. Other state which needs
to follow:

- hw state of the dpll (on/off + dpll registers). Currently we just
  read that out from the hw state, but that doesn't work too well when
  the dpll is in use, but not yet fully enabled. We get away since
  most likely it already has been enabled and so the correct state is
  left behind in the registers. But that doesn't hold for atomic
  modesets when we want to enable all pipes at once.

- Refcount reconstruction for each dpll.

- Cross-checking of all the above. For that we need to keep the dpll
  register state both in the pipe and in the shared_dpll struct, so
  that we can check that every pipe is still connected to a correctly
  configured dpll.

Note that since the refcount resconstruction isn't done yet this will
spill a few WARNs at boot-up while trying to disable pch plls which
have bogus refcounts. But since there's still a pile of refactoring to
do I'd like to lock down the state handling as soon as possible hence
decided against reordering the patches to quiet these WARNs - after
all the issues they're complaining about have existed since forever,
as Jesse can testify by having pch pll states blow up consistently in
his fastboot patches ...

v2: We need to preserve the old shared_dpll since currently the
shared dpll refcount dropping/getting is done in ->mode_set. With
the usual pipe_config infrastructure the old dpll id is already lost
at that point, hence preserve it in the new config.

v3: Rebase on top of the ips patch from Paulo.

v4: We need to unconditionally take over the shared_dpll id from the
old pipe config when e.g. doing a direct pch port -> cpu edp
transition.

v5: Move the saving of the old shared_dpll id to an ealier patch.

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>
drivers/gpu/drm/i915/intel_display.c

index d5932ef..51670ba 100644 (file)
@@ -4998,6 +4998,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        uint32_t tmp;
 
        pipe_config->cpu_transcoder = crtc->pipe;
+       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
@@ -5874,6 +5875,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        uint32_t tmp;
 
        pipe_config->cpu_transcoder = crtc->pipe;
+       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
@@ -5891,6 +5893,16 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
                /* XXX: Can't properly read out the pch dpll pixel multiplier
                 * since we don't have state tracking for pch clocks yet. */
                pipe_config->pixel_multiplier = 1;
+
+               if (HAS_PCH_IBX(dev_priv->dev)) {
+                       pipe_config->shared_dpll = crtc->pipe;
+               } else {
+                       tmp = I915_READ(PCH_DPLL_SEL);
+                       if (tmp & TRANS_DPLLB_SEL(crtc->pipe))
+                               pipe_config->shared_dpll = DPLL_ID_PCH_PLL_B;
+                       else
+                               pipe_config->shared_dpll = DPLL_ID_PCH_PLL_A;
+               }
        } else {
                pipe_config->pixel_multiplier = 1;
        }
@@ -5971,6 +5983,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        uint32_t tmp;
 
        pipe_config->cpu_transcoder = crtc->pipe;
+       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
+
        tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
        if (tmp & TRANS_DDI_FUNC_ENABLE) {
                enum pipe trans_edp_pipe;
@@ -7840,6 +7854,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
        drm_mode_copy(&pipe_config->adjusted_mode, mode);
        drm_mode_copy(&pipe_config->requested_mode, mode);
        pipe_config->cpu_transcoder = to_intel_crtc(crtc)->pipe;
+       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
        /* Compute a starting value for pipe_config->pipe_bpp taking the source
         * plane pixel format and any sink constraints into account. Returns the
@@ -8159,6 +8174,8 @@ intel_pipe_config_compare(struct drm_device *dev,
 
        PIPE_CONF_CHECK_I(ips_enabled);
 
+       PIPE_CONF_CHECK_I(shared_dpll);
+
 #undef PIPE_CONF_CHECK_I
 #undef PIPE_CONF_CHECK_FLAGS
 #undef PIPE_CONF_QUIRK