lkml.org 
[lkml]   [2016]   [Aug]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.12 014/100] drm/i915/ilk: Don't disable SSC source if it's in use
    Date
    From: Lyude <cpaul@redhat.com>

    3.12-stable review patch. If anyone has any objections, please let me know.

    ===============

    commit 476490a945e1f0f6bd58e303058d2d8ca93a974c upstream.

    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 enable SSC in both PCH_DREF_CONTROL and in 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.

    A better solution would be to add refcounts for the SSC source, but for
    now leaving the source clock on should suffice.

    Changes since v4:
    - Fix calculation of final for systems with LVDS panels (fixes BUG() on
    CI test suite)
    Changes since v3:
    - Move temp variable into loop
    - Move checks for using_ssc_source to after we've figured out has_ck505
    - Add using_ssc_source to debug output
    Changes since v2:
    - Fix debug output for when we disable the CPU source
    Changes since v1:
    - Leave the SSC source clock on instead of just shutting it off on all
    of the DPLL configurations.

    Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
    Signed-off-by: Lyude <cpaul@redhat.com>
    Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
    Link: http://patchwork.freedesktop.org/patch/msgid/1465916649-10228-1-git-send-email-cpaul@redhat.com
    Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
    Signed-off-by: Jiri Slaby <jslaby@suse.cz>
    ---
    drivers/gpu/drm/i915/intel_display.c | 48 +++++++++++++++++++++++++-----------
    1 file changed, 34 insertions(+), 14 deletions(-)

    diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
    index af46a33d8715..05f8b51cd42a 100644
    --- a/drivers/gpu/drm/i915/intel_display.c
    +++ b/drivers/gpu/drm/i915/intel_display.c
    @@ -5126,12 +5126,14 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
    struct drm_i915_private *dev_priv = dev->dev_private;
    struct drm_mode_config *mode_config = &dev->mode_config;
    struct intel_encoder *encoder;
    + int i;
    u32 val, final;
    bool has_lvds = false;
    bool has_cpu_edp = false;
    bool has_panel = false;
    bool has_ck505 = false;
    bool can_ssc = false;
    + bool using_ssc_source = false;

    /* We need to take the global config into account */
    list_for_each_entry(encoder, &mode_config->encoder_list,
    @@ -5157,8 +5159,22 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
    can_ssc = true;
    }

    - DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
    - has_panel, has_lvds, has_ck505);
    + /* Check if any DPLLs are using the SSC source */
    + for (i = 0; i < dev_priv->num_shared_dpll; i++) {
    + u32 temp = I915_READ(PCH_DPLL(i));
    +
    + if (!(temp & DPLL_VCO_ENABLE))
    + continue;
    +
    + if ((temp & PLL_REF_INPUT_MASK) ==
    + PLLB_REF_INPUT_SPREADSPECTRUMIN) {
    + using_ssc_source = true;
    + break;
    + }
    + }
    +
    + DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
    + has_panel, has_lvds, has_ck505, using_ssc_source);

    /* Ironlake: try to setup display ref clock before DPLL
    * enabling. This is only under driver's control after
    @@ -5195,9 +5211,9 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
    final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
    } else
    final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
    - } else {
    - final |= DREF_SSC_SOURCE_DISABLE;
    - final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
    + } else if (using_ssc_source) {
    + final |= DREF_SSC_SOURCE_ENABLE;
    + final |= DREF_SSC1_ENABLE;
    }

    if (final == val)
    @@ -5244,7 +5260,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
    POSTING_READ(PCH_DREF_CONTROL);
    udelay(200);
    } else {
    - DRM_DEBUG_KMS("Disabling SSC entirely\n");
    + DRM_DEBUG_KMS("Disabling CPU source output\n");

    val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;

    @@ -5255,16 +5271,20 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
    POSTING_READ(PCH_DREF_CONTROL);
    udelay(200);

    - /* Turn off the SSC source */
    - val &= ~DREF_SSC_SOURCE_MASK;
    - val |= DREF_SSC_SOURCE_DISABLE;
    + if (!using_ssc_source) {
    + DRM_DEBUG_KMS("Disabling SSC source\n");

    - /* Turn off SSC1 */
    - val &= ~DREF_SSC1_ENABLE;
    + /* Turn off the SSC source */
    + val &= ~DREF_SSC_SOURCE_MASK;
    + val |= DREF_SSC_SOURCE_DISABLE;

    - I915_WRITE(PCH_DREF_CONTROL, val);
    - POSTING_READ(PCH_DREF_CONTROL);
    - udelay(200);
    + /* Turn off SSC1 */
    + val &= ~DREF_SSC1_ENABLE;
    +
    + I915_WRITE(PCH_DREF_CONTROL, val);
    + POSTING_READ(PCH_DREF_CONTROL);
    + udelay(200);
    + }
    }

    BUG_ON(val != final);
    --
    2.9.3
    \
     
     \ /
      Last update: 2016-09-17 09:57    [W:4.049 / U:0.544 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site