Skip to content

Commit

Permalink
drm/i915: Skip modifying PCH DREF if not changing clock sources
Browse files Browse the repository at this point in the history
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 <chris@chris-wilson.co.uk>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
[danvet: Appease checkpatch by deleting a space after a ~]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Chris Wilson authored and Daniel Vetter committed Apr 2, 2013
1 parent 31ad8ec commit 74cfd7a
Showing 1 changed file with 61 additions and 22 deletions.
83 changes: 61 additions & 22 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -4701,7 +4701,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;
Expand Down Expand Up @@ -4744,70 +4744,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;

/* 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. */
Expand Down

0 comments on commit 74cfd7a

Please sign in to comment.