Thanks to Ville Syrjälä for pointing me towards the cause of this issue. Unfortunately one of the sideaffects of having the refclk for a DPLL set to SSC is that as long as it's set to SSC, the GPU will prevent us from powering down any of the pipes or transcoders using it. A couple of BIOSes, despite the fact they don't actually need it, enable SSC both in PCH_DREF_CONTROL and on the DPLL configurations. This causes issues on the first modeset, since we don't expect SSC to be left on and as a result, can't successfully power down the pipes or the transcoders using it. Here's an example from this Dell OptiPlex 990: [drm:intel_modeset_init] SSC enabled by BIOS, overriding VBT which says disabled [drm:intel_modeset_init] 2 display pipes available. [drm:intel_update_cdclk] Current CD clock rate: 400000 kHz [drm:intel_update_max_cdclk] Max CD clock rate: 400000 kHz [drm:intel_update_max_cdclk] Max dotclock rate: 360000 kHz vgaarb: device changed decodes: PCI:0000:00:02.0,olddecodes=io+mem,decodes=io+mem:owns=io+mem [drm:intel_crt_reset] crt adpa set to 0xf40000 [drm:intel_dp_init_connector] Adding DP connector on port C [drm:intel_dp_aux_init] registering DPDDC-C bus for card0-DP-1 [drm:ironlake_init_pch_refclk] has_panel 0 has_lvds 0 has_ck505 0 [drm:ironlake_init_pch_refclk] Disabling SSC entirely … later we try committing the first modeset … [drm:intel_dump_pipe_config] [CRTC:26][modeset] config ffff88041b02e800 for pipe A [drm:intel_dump_pipe_config] cpu_transcoder: A … [drm:intel_dump_pipe_config] dpll_hw_state: dpll: 0xc4016001, dpll_md: 0x0, fp0: 0x20e08, fp1: 0x30d07 [drm:intel_dump_pipe_config] planes on this crtc [drm:intel_dump_pipe_config] STANDARD PLANE:23 plane: 0.0 idx: 0 enabled [drm:intel_dump_pipe_config] FB:42, fb = 800x600 format = 0x34325258 [drm:intel_dump_pipe_config] scaler:0 src (0, 0) 800x600 dst (0, 0) 800x600 [drm:intel_dump_pipe_config] CURSOR PLANE:25 plane: 0.1 idx: 1 disabled, scaler_id = 0 [drm:intel_dump_pipe_config] STANDARD PLANE:27 plane: 0.1 idx: 2 disabled, scaler_id = 0 [drm:intel_get_shared_dpll] CRTC:26 allocated PCH DPLL A [drm:intel_get_shared_dpll] using PCH DPLL A for pipe A [drm:ilk_audio_codec_disable] Disable audio codec on port C, pipe A [drm:intel_disable_pipe] disabling pipe A ------------[ cut here ]------------ WARNING: CPU: 1 PID: 130 at drivers/gpu/drm/i915/intel_display.c:1146 intel_disable_pipe+0x297/0x2d0 [i915] pipe_off wait timed out … ---[ end trace 94fc8aa03ae139e8 ]--- [drm:intel_dp_link_down] [drm:ironlake_crtc_disable [i915]] *ERROR* failed to disable transcoder A Later modesets succeed since they reset the DPLL's configuration anyway, but this is enough to get stuck with a big fat warning in dmesg. Normally we'd need to add some sort of ref counting mechanism to the CRTCs so we avoid accidentally trying to shut off a shared resource, but since ignore what the BIOS does anyway and we shut off the refclks before any modesets, this workaround should suffice for now. Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Lyude <cpaul@xxxxxxxxxx> --- drivers/gpu/drm/i915/intel_display.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d500e6f..3fb6025 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8230,7 +8230,8 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; - u32 val, final; + int i; + u32 val, temp, final; bool has_lvds = false; bool has_cpu_edp = false; bool has_panel = false; @@ -8369,6 +8370,22 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) I915_WRITE(PCH_DREF_CONTROL, val); POSTING_READ(PCH_DREF_CONTROL); udelay(200); + + /* Unset SSC as the refclk for all of the DPLLs */ + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + temp = I915_READ(PCH_DPLL(i)); + + if (!(temp & PLLB_REF_INPUT_SPREADSPECTRUMIN)) + continue; + + DRM_DEBUG_KMS("Disabling SSC refclk for %s\n", + dev_priv->shared_dplls[i].name); + + /* Change refclk to DREFCLK */ + temp &= ~PLL_REF_INPUT_MASK; + + I915_WRITE(PCH_DPLL(i), temp); + } } BUG_ON(val != final); -- 2.5.5 -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html