diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-03-26 19:33:04 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-04-02 14:25:34 -0400 |
commit | 74cfd7ac5e1119ec3275d769ed9e27bcd97cf896 (patch) | |
tree | ae085468d69dce81d81a5eebe801b8e01f347001 /drivers/gpu/drm | |
parent | 31ad8ec6a6145f9ac978a112801dbde33d44b9d1 (diff) |
drm/i915: Skip modifying PCH DREF if not changing clock sources
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>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 83 |
1 files changed, 61 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5e8b91f2c529..0e172ced8f0e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4701,7 +4701,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) | |||
4701 | struct drm_i915_private *dev_priv = dev->dev_private; | 4701 | struct drm_i915_private *dev_priv = dev->dev_private; |
4702 | struct drm_mode_config *mode_config = &dev->mode_config; | 4702 | struct drm_mode_config *mode_config = &dev->mode_config; |
4703 | struct intel_encoder *encoder; | 4703 | struct intel_encoder *encoder; |
4704 | u32 temp; | 4704 | u32 val, final; |
4705 | bool has_lvds = false; | 4705 | bool has_lvds = false; |
4706 | bool has_cpu_edp = false; | 4706 | bool has_cpu_edp = false; |
4707 | bool has_pch_edp = false; | 4707 | bool has_pch_edp = false; |
@@ -4744,70 +4744,109 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) | |||
4744 | * PCH B stepping, previous chipset stepping should be | 4744 | * PCH B stepping, previous chipset stepping should be |
4745 | * ignoring this setting. | 4745 | * ignoring this setting. |
4746 | */ | 4746 | */ |
4747 | temp = I915_READ(PCH_DREF_CONTROL); | 4747 | val = I915_READ(PCH_DREF_CONTROL); |
4748 | |||
4749 | /* As we must carefully and slowly disable/enable each source in turn, | ||
4750 | * compute the final state we want first and check if we need to | ||
4751 | * make any changes at all. | ||
4752 | */ | ||
4753 | final = val; | ||
4754 | final &= ~DREF_NONSPREAD_SOURCE_MASK; | ||
4755 | if (has_ck505) | ||
4756 | final |= DREF_NONSPREAD_CK505_ENABLE; | ||
4757 | else | ||
4758 | final |= DREF_NONSPREAD_SOURCE_ENABLE; | ||
4759 | |||
4760 | final &= ~DREF_SSC_SOURCE_MASK; | ||
4761 | final &= ~DREF_CPU_SOURCE_OUTPUT_MASK; | ||
4762 | final &= ~DREF_SSC1_ENABLE; | ||
4763 | |||
4764 | if (has_panel) { | ||
4765 | final |= DREF_SSC_SOURCE_ENABLE; | ||
4766 | |||
4767 | if (intel_panel_use_ssc(dev_priv) && can_ssc) | ||
4768 | final |= DREF_SSC1_ENABLE; | ||
4769 | |||
4770 | if (has_cpu_edp) { | ||
4771 | if (intel_panel_use_ssc(dev_priv) && can_ssc) | ||
4772 | final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; | ||
4773 | else | ||
4774 | final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; | ||
4775 | } else | ||
4776 | final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; | ||
4777 | } else { | ||
4778 | final |= DREF_SSC_SOURCE_DISABLE; | ||
4779 | final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; | ||
4780 | } | ||
4781 | |||
4782 | if (final == val) | ||
4783 | return; | ||
4784 | |||
4748 | /* Always enable nonspread source */ | 4785 | /* Always enable nonspread source */ |
4749 | temp &= ~DREF_NONSPREAD_SOURCE_MASK; | 4786 | val &= ~DREF_NONSPREAD_SOURCE_MASK; |
4750 | 4787 | ||
4751 | if (has_ck505) | 4788 | if (has_ck505) |
4752 | temp |= DREF_NONSPREAD_CK505_ENABLE; | 4789 | val |= DREF_NONSPREAD_CK505_ENABLE; |
4753 | else | 4790 | else |
4754 | temp |= DREF_NONSPREAD_SOURCE_ENABLE; | 4791 | val |= DREF_NONSPREAD_SOURCE_ENABLE; |
4755 | 4792 | ||
4756 | if (has_panel) { | 4793 | if (has_panel) { |
4757 | temp &= ~DREF_SSC_SOURCE_MASK; | 4794 | val &= ~DREF_SSC_SOURCE_MASK; |
4758 | temp |= DREF_SSC_SOURCE_ENABLE; | 4795 | val |= DREF_SSC_SOURCE_ENABLE; |
4759 | 4796 | ||
4760 | /* SSC must be turned on before enabling the CPU output */ | 4797 | /* SSC must be turned on before enabling the CPU output */ |
4761 | if (intel_panel_use_ssc(dev_priv) && can_ssc) { | 4798 | if (intel_panel_use_ssc(dev_priv) && can_ssc) { |
4762 | DRM_DEBUG_KMS("Using SSC on panel\n"); | 4799 | DRM_DEBUG_KMS("Using SSC on panel\n"); |
4763 | temp |= DREF_SSC1_ENABLE; | 4800 | val |= DREF_SSC1_ENABLE; |
4764 | } else | 4801 | } else |
4765 | temp &= ~DREF_SSC1_ENABLE; | 4802 | val &= ~DREF_SSC1_ENABLE; |
4766 | 4803 | ||
4767 | /* Get SSC going before enabling the outputs */ | 4804 | /* Get SSC going before enabling the outputs */ |
4768 | I915_WRITE(PCH_DREF_CONTROL, temp); | 4805 | I915_WRITE(PCH_DREF_CONTROL, val); |
4769 | POSTING_READ(PCH_DREF_CONTROL); | 4806 | POSTING_READ(PCH_DREF_CONTROL); |
4770 | udelay(200); | 4807 | udelay(200); |
4771 | 4808 | ||
4772 | temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; | 4809 | val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; |
4773 | 4810 | ||
4774 | /* Enable CPU source on CPU attached eDP */ | 4811 | /* Enable CPU source on CPU attached eDP */ |
4775 | if (has_cpu_edp) { | 4812 | if (has_cpu_edp) { |
4776 | if (intel_panel_use_ssc(dev_priv) && can_ssc) { | 4813 | if (intel_panel_use_ssc(dev_priv) && can_ssc) { |
4777 | DRM_DEBUG_KMS("Using SSC on eDP\n"); | 4814 | DRM_DEBUG_KMS("Using SSC on eDP\n"); |
4778 | temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; | 4815 | val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; |
4779 | } | 4816 | } |
4780 | else | 4817 | else |
4781 | temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; | 4818 | val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; |
4782 | } else | 4819 | } else |
4783 | temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE; | 4820 | val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; |
4784 | 4821 | ||
4785 | I915_WRITE(PCH_DREF_CONTROL, temp); | 4822 | I915_WRITE(PCH_DREF_CONTROL, val); |
4786 | POSTING_READ(PCH_DREF_CONTROL); | 4823 | POSTING_READ(PCH_DREF_CONTROL); |
4787 | udelay(200); | 4824 | udelay(200); |
4788 | } else { | 4825 | } else { |
4789 | DRM_DEBUG_KMS("Disabling SSC entirely\n"); | 4826 | DRM_DEBUG_KMS("Disabling SSC entirely\n"); |
4790 | 4827 | ||
4791 | temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; | 4828 | val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; |
4792 | 4829 | ||
4793 | /* Turn off CPU output */ | 4830 | /* Turn off CPU output */ |
4794 | temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE; | 4831 | val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; |
4795 | 4832 | ||
4796 | I915_WRITE(PCH_DREF_CONTROL, temp); | 4833 | I915_WRITE(PCH_DREF_CONTROL, val); |
4797 | POSTING_READ(PCH_DREF_CONTROL); | 4834 | POSTING_READ(PCH_DREF_CONTROL); |
4798 | udelay(200); | 4835 | udelay(200); |
4799 | 4836 | ||
4800 | /* Turn off the SSC source */ | 4837 | /* Turn off the SSC source */ |
4801 | temp &= ~DREF_SSC_SOURCE_MASK; | 4838 | val &= ~DREF_SSC_SOURCE_MASK; |
4802 | temp |= DREF_SSC_SOURCE_DISABLE; | 4839 | val |= DREF_SSC_SOURCE_DISABLE; |
4803 | 4840 | ||
4804 | /* Turn off SSC1 */ | 4841 | /* Turn off SSC1 */ |
4805 | temp &= ~ DREF_SSC1_ENABLE; | 4842 | val &= ~DREF_SSC1_ENABLE; |
4806 | 4843 | ||
4807 | I915_WRITE(PCH_DREF_CONTROL, temp); | 4844 | I915_WRITE(PCH_DREF_CONTROL, val); |
4808 | POSTING_READ(PCH_DREF_CONTROL); | 4845 | POSTING_READ(PCH_DREF_CONTROL); |
4809 | udelay(200); | 4846 | udelay(200); |
4810 | } | 4847 | } |
4848 | |||
4849 | BUG_ON(val != final); | ||
4811 | } | 4850 | } |
4812 | 4851 | ||
4813 | /* Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O. */ | 4852 | /* Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O. */ |