On Wed, 2013-02-06 at 11:10 +0000, Chris Wilson wrote:
> Modifying the clock sources (via the DREF control on the PCH) is a slow
> multi-stage process as we need to let the clocks stabilise between each
> stage. If we are not actually changing the clock sources, then we can
> return early.
> 
> Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/intel_display.c |   83 
> +++++++++++++++++++++++++---------
>  1 file changed, 61 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c 
> b/drivers/gpu/drm/i915/intel_display.c
> index d75c6a0..f1dbd01 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -4749,7 +4749,7 @@ 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;
> -     u32 temp;
> +     u32 val, final;
>       bool has_lvds = false;
>       bool has_cpu_edp = false;
>       bool has_pch_edp = false;
> @@ -4792,70 +4792,109 @@ static void ironlake_init_pch_refclk(struct 
> drm_device *dev)
>        * PCH B stepping, previous chipset stepping should be
>        * ignoring this setting.
>        */
> -     temp = I915_READ(PCH_DREF_CONTROL);
> +     val = I915_READ(PCH_DREF_CONTROL);
> +
> +     /* As we must carefully and slowly disable/enable each source in turn,
> +      * compute the final state we want first and check if we need to
> +      * make any changes at all.
> +      */
> +     final = val;
> +     final &= ~DREF_NONSPREAD_SOURCE_MASK;
> +     if (has_ck505)
> +             final |= DREF_NONSPREAD_CK505_ENABLE;
> +     else
> +             final |= DREF_NONSPREAD_SOURCE_ENABLE;
> +
> +     final &= ~DREF_SSC_SOURCE_MASK;
> +     final &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
> +     final &= ~DREF_SSC1_ENABLE;
> +
> +     if (has_panel) {
> +             final |= DREF_SSC_SOURCE_ENABLE;
> +
> +             if (intel_panel_use_ssc(dev_priv) && can_ssc)
> +                     final |= DREF_SSC1_ENABLE;
> +
> +             if (has_cpu_edp) {
> +                     if (intel_panel_use_ssc(dev_priv) && can_ssc)
> +                             final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
> +                     else
> +                             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;
> +     }
> +
> +     if (final == val)
> +             return;
> +

Nitpick: this would be clearer in a seperate function with a
'check_only' param, then the below could be removed.

>       /* Always enable nonspread source */
> -     temp &= ~DREF_NONSPREAD_SOURCE_MASK;
> +     val &= ~DREF_NONSPREAD_SOURCE_MASK;
>  
>       if (has_ck505)
> -             temp |= DREF_NONSPREAD_CK505_ENABLE;
> +             val |= DREF_NONSPREAD_CK505_ENABLE;
>       else
> -             temp |= DREF_NONSPREAD_SOURCE_ENABLE;
> +             val |= DREF_NONSPREAD_SOURCE_ENABLE;
>  
>       if (has_panel) {
> -             temp &= ~DREF_SSC_SOURCE_MASK;
> -             temp |= DREF_SSC_SOURCE_ENABLE;
> +             val &= ~DREF_SSC_SOURCE_MASK;
> +             val |= DREF_SSC_SOURCE_ENABLE;
>  
>               /* SSC must be turned on before enabling the CPU output  */
>               if (intel_panel_use_ssc(dev_priv) && can_ssc) {
>                       DRM_DEBUG_KMS("Using SSC on panel\n");
> -                     temp |= DREF_SSC1_ENABLE;
> +                     val |= DREF_SSC1_ENABLE;
>               } else
> -                     temp &= ~DREF_SSC1_ENABLE;
> +                     val &= ~DREF_SSC1_ENABLE;
>  
>               /* Get SSC going before enabling the outputs */
> -             I915_WRITE(PCH_DREF_CONTROL, temp);
> +             I915_WRITE(PCH_DREF_CONTROL, val);
>               POSTING_READ(PCH_DREF_CONTROL);
>               udelay(200);
>  
> -             temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
> +             val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
>  
>               /* Enable CPU source on CPU attached eDP */
>               if (has_cpu_edp) {
>                       if (intel_panel_use_ssc(dev_priv) && can_ssc) {
>                               DRM_DEBUG_KMS("Using SSC on eDP\n");
> -                             temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
> +                             val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
>                       }
>                       else
> -                             temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
> +                             val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
>               } else
> -                     temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
> +                     val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
>  
> -             I915_WRITE(PCH_DREF_CONTROL, temp);
> +             I915_WRITE(PCH_DREF_CONTROL, val);
>               POSTING_READ(PCH_DREF_CONTROL);
>               udelay(200);
>       } else {
>               DRM_DEBUG_KMS("Disabling SSC entirely\n");
>  
> -             temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
> +             val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
>  
>               /* Turn off CPU output */
> -             temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
> +             val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
>  
> -             I915_WRITE(PCH_DREF_CONTROL, temp);
> +             I915_WRITE(PCH_DREF_CONTROL, val);
>               POSTING_READ(PCH_DREF_CONTROL);
>               udelay(200);
>  
>               /* Turn off the SSC source */
> -             temp &= ~DREF_SSC_SOURCE_MASK;
> -             temp |= DREF_SSC_SOURCE_DISABLE;
> +             val &= ~DREF_SSC_SOURCE_MASK;
> +             val |= DREF_SSC_SOURCE_DISABLE;
>  
>               /* Turn off SSC1 */
> -             temp &= ~ DREF_SSC1_ENABLE;
> +             val &= ~ DREF_SSC1_ENABLE;
>  
> -             I915_WRITE(PCH_DREF_CONTROL, temp);
> +             I915_WRITE(PCH_DREF_CONTROL, val);
>               POSTING_READ(PCH_DREF_CONTROL);
>               udelay(200);
>       }
> +
> +     BUG_ON(val != final);
>  }
>  
>  /* Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O. */


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to