aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c100
1 files changed, 97 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fb3f4aaca2c4..f1bb2e2ec173 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2675,6 +2675,97 @@ static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
2675 return true; 2675 return true;
2676} 2676}
2677 2677
2678/* Program iCLKIP clock to the desired frequency */
2679static void lpt_program_iclkip(struct drm_crtc *crtc)
2680{
2681 struct drm_device *dev = crtc->dev;
2682 struct drm_i915_private *dev_priv = dev->dev_private;
2683 u32 divsel, phaseinc, auxdiv, phasedir = 0;
2684 u32 temp;
2685
2686 /* It is necessary to ungate the pixclk gate prior to programming
2687 * the divisors, and gate it back when it is done.
2688 */
2689 I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
2690
2691 /* Disable SSCCTL */
2692 intel_sbi_write(dev_priv, SBI_SSCCTL6,
2693 intel_sbi_read(dev_priv, SBI_SSCCTL6) |
2694 SBI_SSCCTL_DISABLE);
2695
2696 /* 20MHz is a corner case which is out of range for the 7-bit divisor */
2697 if (crtc->mode.clock == 20000) {
2698 auxdiv = 1;
2699 divsel = 0x41;
2700 phaseinc = 0x20;
2701 } else {
2702 /* The iCLK virtual clock root frequency is in MHz,
2703 * but the crtc->mode.clock in in KHz. To get the divisors,
2704 * it is necessary to divide one by another, so we
2705 * convert the virtual clock precision to KHz here for higher
2706 * precision.
2707 */
2708 u32 iclk_virtual_root_freq = 172800 * 1000;
2709 u32 iclk_pi_range = 64;
2710 u32 desired_divisor, msb_divisor_value, pi_value;
2711
2712 desired_divisor = (iclk_virtual_root_freq / crtc->mode.clock);
2713 msb_divisor_value = desired_divisor / iclk_pi_range;
2714 pi_value = desired_divisor % iclk_pi_range;
2715
2716 auxdiv = 0;
2717 divsel = msb_divisor_value - 2;
2718 phaseinc = pi_value;
2719 }
2720
2721 /* This should not happen with any sane values */
2722 WARN_ON(SBI_SSCDIVINTPHASE_DIVSEL(divsel) &
2723 ~SBI_SSCDIVINTPHASE_DIVSEL_MASK);
2724 WARN_ON(SBI_SSCDIVINTPHASE_DIR(phasedir) &
2725 ~SBI_SSCDIVINTPHASE_INCVAL_MASK);
2726
2727 DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
2728 crtc->mode.clock,
2729 auxdiv,
2730 divsel,
2731 phasedir,
2732 phaseinc);
2733
2734 /* Program SSCDIVINTPHASE6 */
2735 temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6);
2736 temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
2737 temp |= SBI_SSCDIVINTPHASE_DIVSEL(divsel);
2738 temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK;
2739 temp |= SBI_SSCDIVINTPHASE_INCVAL(phaseinc);
2740 temp |= SBI_SSCDIVINTPHASE_DIR(phasedir);
2741 temp |= SBI_SSCDIVINTPHASE_PROPAGATE;
2742
2743 intel_sbi_write(dev_priv,
2744 SBI_SSCDIVINTPHASE6,
2745 temp);
2746
2747 /* Program SSCAUXDIV */
2748 temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6);
2749 temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1);
2750 temp |= SBI_SSCAUXDIV_FINALDIV2SEL(auxdiv);
2751 intel_sbi_write(dev_priv,
2752 SBI_SSCAUXDIV6,
2753 temp);
2754
2755
2756 /* Enable modulator and associated divider */
2757 temp = intel_sbi_read(dev_priv, SBI_SSCCTL6);
2758 temp &= ~SBI_SSCCTL_DISABLE;
2759 intel_sbi_write(dev_priv,
2760 SBI_SSCCTL6,
2761 temp);
2762
2763 /* Wait for initialization time */
2764 udelay(24);
2765
2766 I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
2767}
2768
2678/* 2769/*
2679 * Enable PCH resources required for PCH ports: 2770 * Enable PCH resources required for PCH ports:
2680 * - PCH PLLs 2771 * - PCH PLLs
@@ -2694,11 +2785,14 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
2694 /* For PCH output, training FDI link */ 2785 /* For PCH output, training FDI link */
2695 dev_priv->display.fdi_link_train(crtc); 2786 dev_priv->display.fdi_link_train(crtc);
2696 2787
2697 intel_enable_pch_pll(intel_crtc); 2788 if (HAS_PCH_LPT(dev)) {
2698 2789 DRM_DEBUG_KMS("LPT detected: programming iCLKIP\n");
2699 if (HAS_PCH_CPT(dev)) { 2790 lpt_program_iclkip(crtc);
2791 } else if (HAS_PCH_CPT(dev)) {
2700 u32 sel; 2792 u32 sel;
2701 2793
2794 intel_enable_pch_pll(intel_crtc);
2795
2702 temp = I915_READ(PCH_DPLL_SEL); 2796 temp = I915_READ(PCH_DPLL_SEL);
2703 switch (pipe) { 2797 switch (pipe) {
2704 default: 2798 default: