On Wed,  5 Oct 2011 10:25:21 -0700
Jesse Barnes <jbar...@virtuousgeek.org> wrote:

> Handle PLL allocation and transcoder select bits on CPT+.

Updated patch that fixes the bug with VGA plus two HDMI.  Was missing
the composite sync bits in the FDI TX side (setting them everywhere
here just to be safe).

-- 
Jesse Barnes, Intel Open Source Technology Center

From 3efb84701437f2d1eae3fb68c1259c2bb5a0c518 Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbar...@virtuousgeek.org>
Date: Fri, 2 Sep 2011 15:28:39 -0700
Subject: [PATCH] drm/i915: more 3 pipe support

Handle PLL allocation and transcoder select bits on CPT+.

Signed-off-by: Jesse Barnes <jbar...@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_reg.h      |    1 +
 drivers/gpu/drm/i915/intel_crt.c     |   13 +---
 drivers/gpu/drm/i915/intel_display.c |  101 +++++++++++++++++++++-------------
 drivers/gpu/drm/i915/intel_drv.h     |    3 +
 drivers/gpu/drm/i915/intel_hdmi.c    |   10 +--
 5 files changed, 74 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7659075..b31f253 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3167,6 +3167,7 @@
 #define  FDI_LINK_TRAIN_NONE_IVB            (3<<8)
 
 /* both Tx and Rx */
+#define  FDI_COMPOSITE_SYNC            (1<<11)
 #define  FDI_LINK_TRAIN_AUTO           (1<<10)
 #define  FDI_SCRAMBLING_ENABLE          (0<<7)
 #define  FDI_SCRAMBLING_DISABLE         (1<<7)
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 0979d88..da769e6 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -152,17 +152,12 @@ static void intel_crt_mode_set(struct drm_encoder 
*encoder,
        if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
                adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
-       if (intel_crtc->pipe == 0) {
-               if (HAS_PCH_CPT(dev))
-                       adpa |= PORT_TRANS_A_SEL_CPT;
-               else
+       if (HAS_PCH_CPT(dev))
+               adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
+       else if (intel_crtc->pipe == 0)
                        adpa |= ADPA_PIPE_A_SELECT;
-       } else {
-               if (HAS_PCH_CPT(dev))
-                       adpa |= PORT_TRANS_B_SEL_CPT;
-               else
+       else
                        adpa |= ADPA_PIPE_B_SELECT;
-       }
 
        if (!HAS_PCH_SPLIT(dev))
                I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 058dc05..e63a187 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -802,6 +802,9 @@ static void assert_pch_pll(struct drm_i915_private 
*dev_priv,
        u32 val;
        bool cur_state;
 
+       if (pipe > 1)
+               return;
+
        reg = PCH_DPLL(pipe);
        val = I915_READ(reg);
        cur_state = !!(val & DPLL_VCO_ENABLE);
@@ -2366,6 +2369,7 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
        temp = I915_READ(reg);
        temp &= ~FDI_RX_SYMBOL_LOCK;
        temp &= ~FDI_RX_BIT_LOCK;
+       temp |= FDI_COMPOSITE_SYNC;
        I915_WRITE(reg, temp);
        I915_READ(reg);
        udelay(150);
@@ -2377,6 +2381,7 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
        temp |= (intel_crtc->fdi_lanes - 1) << 19;
        temp &= ~FDI_LINK_TRAIN_NONE;
        temp |= FDI_LINK_TRAIN_PATTERN_1;
+       temp |= FDI_COMPOSITE_SYNC;
        I915_WRITE(reg, temp | FDI_TX_ENABLE);
 
        reg = FDI_RX_CTL(pipe);
@@ -2704,6 +2709,8 @@ static void ironlake_fdi_pll_enable(struct drm_crtc *crtc)
        temp &= ~((0x7 << 19) | (0x7 << 16));
        temp |= (intel_crtc->fdi_lanes - 1) << 19;
        temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+       if (HAS_PCH_CPT(dev))
+               temp |= 1<<11;
        I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
 
        POSTING_READ(reg);
@@ -2869,7 +2876,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp;
+       u32 reg, temp, transc_sel;
 
        /* For PCH output, training FDI link */
        dev_priv->display.fdi_link_train(crtc);
@@ -2877,6 +2884,9 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        intel_enable_pch_pll(dev_priv, pipe);
 
        if (HAS_PCH_CPT(dev)) {
+               transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL :
+                       TRANSC_DPLLB_SEL;
+
                /* Be sure PCH DPLL SEL is set */
                temp = I915_READ(PCH_DPLL_SEL);
                if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0)
@@ -2884,7 +2894,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
                else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0)
                        temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
                else if (pipe == 2 && (temp & TRANSC_DPLL_ENABLE) == 0)
-                       temp |= (TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
+                       temp |= (TRANSC_DPLL_ENABLE | transc_sel);
                I915_WRITE(PCH_DPLL_SEL, temp);
        }
 
@@ -3056,8 +3066,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
                        temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
                        break;
                case 2:
-                       /* FIXME: manage transcoder PLLs? */
-                       temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
+                       /* C shares PLL A or B */
+                       temp &= ~(TRANSC_DPLL_ENABLE | TRANSB_DPLLB_SEL);
                        break;
                default:
                        BUG(); /* wtf */
@@ -3066,7 +3076,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
        }
 
        /* disable PCH DPLL */
-       intel_disable_pch_pll(dev_priv, pipe);
+       if (!intel_crtc->no_pll)
+               intel_disable_pch_pll(dev_priv, pipe);
 
        /* Switch from PCDclk to Rawclk */
        reg = FDI_RX_CTL(pipe);
@@ -5216,11 +5227,7 @@ static int ironlake_get_refclk(struct drm_crtc *crtc)
                return dev_priv->lvds_ssc_freq * 1000;
        }
 
-       /* PCH ports use a 120 MHz refclk */
-       if (!edp_encoder || intel_encoder_is_pch_edp(&edp_encoder->base))
-               return 120000;
-       else
-               return 96000;
+       return 120000;
 }
 
 static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
@@ -5486,16 +5493,32 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        drm_mode_debug_printmodeline(mode);
 
        /* PCH eDP needs FDI, but CPU eDP does not */
-       if (!has_edp_encoder || 
intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+       if (!intel_crtc->no_pll &&
+           (!has_edp_encoder ||
+            intel_encoder_is_pch_edp(&has_edp_encoder->base))) {
                I915_WRITE(PCH_FP0(pipe), fp);
                I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
 
                POSTING_READ(PCH_DPLL(pipe));
                udelay(150);
+       } else {
+               if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) &&
+                   fp == I915_READ(PCH_FP0(0))) {
+                       intel_crtc->use_pll_a = true;
+                       DRM_DEBUG_KMS("using pipe a dpll\n");
+               } else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) &&
+                          fp == I915_READ(PCH_FP0(1))) {
+                       intel_crtc->use_pll_a = false;
+                       DRM_DEBUG_KMS("using pipe b dpll\n");
+               } else
+                       DRM_DEBUG_KMS("no matching PLL configuration for pipe 
2\n");
        }
 
        /* enable transcoder DPLL */
+#if 1
        if (HAS_PCH_CPT(dev)) {
+               u32 transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL :
+                       TRANSC_DPLLB_SEL;
                temp = I915_READ(PCH_DPLL_SEL);
                switch (pipe) {
                case 0:
@@ -5505,8 +5528,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                        temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL;
                        break;
                case 2:
-                       /* FIXME: manage transcoder PLLs? */
-                       temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL;
+                       temp |= TRANSC_DPLL_ENABLE | transc_sel;
                        break;
                default:
                        BUG();
@@ -5516,7 +5538,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                POSTING_READ(PCH_DPLL_SEL);
                udelay(150);
        }
-
+#endif
        /* The LVDS pin pair needs to be on before the DPLLs are enabled.
         * This is an exception to the general rule that mode_set doesn't turn
         * things on.
@@ -5524,17 +5546,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        if (is_lvds) {
                temp = I915_READ(PCH_LVDS);
                temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-               if (pipe == 1) {
-                       if (HAS_PCH_CPT(dev))
-                               temp |= PORT_TRANS_B_SEL_CPT;
-                       else
-                               temp |= LVDS_PIPEB_SELECT;
-               } else {
-                       if (HAS_PCH_CPT(dev))
-                               temp &= ~PORT_TRANS_SEL_MASK;
-                       else
-                               temp &= ~LVDS_PIPEB_SELECT;
-               }
+               if (HAS_PCH_CPT(dev))
+                   temp |= PORT_TRANS_SEL_CPT(pipe);
+               else if (pipe == 1)
+                       temp |= LVDS_PIPEB_SELECT;
+               else
+                       temp &= ~LVDS_PIPEB_SELECT;
+
                /* set the corresponsding LVDS_BORDER bit */
                temp |= dev_priv->lvds_border_bits;
                /* Set the B0-B3 data pairs corresponding to whether we're 
going to
@@ -5584,8 +5602,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                I915_WRITE(TRANSDPLINK_N1(pipe), 0);
        }
 
-       if (!has_edp_encoder ||
-           intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+       if (!intel_crtc->no_pll &&
+           (!has_edp_encoder ||
+            intel_encoder_is_pch_edp(&has_edp_encoder->base))) {
                I915_WRITE(PCH_DPLL(pipe), dpll);
 
                /* Wait for the clocks to stabilize. */
@@ -5601,18 +5620,20 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        intel_crtc->lowfreq_avail = false;
-       if (is_lvds && has_reduced_clock && i915_powersave) {
-               I915_WRITE(PCH_FP1(pipe), fp2);
-               intel_crtc->lowfreq_avail = true;
-               if (HAS_PIPE_CXSR(dev)) {
-                       DRM_DEBUG_KMS("enabling CxSR downclocking\n");
-                       pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
-               }
-       } else {
-               I915_WRITE(PCH_FP1(pipe), fp);
-               if (HAS_PIPE_CXSR(dev)) {
-                       DRM_DEBUG_KMS("disabling CxSR downclocking\n");
-                       pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+       if (!intel_crtc->no_pll) {
+               if (is_lvds && has_reduced_clock && i915_powersave) {
+                       I915_WRITE(PCH_FP1(pipe), fp2);
+                       intel_crtc->lowfreq_avail = true;
+                       if (HAS_PIPE_CXSR(dev)) {
+                               DRM_DEBUG_KMS("enabling CxSR downclocking\n");
+                               pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+                       }
+               } else {
+                       I915_WRITE(PCH_FP1(pipe), fp);
+                       if (HAS_PIPE_CXSR(dev)) {
+                               DRM_DEBUG_KMS("disabling CxSR downclocking\n");
+                               pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+                       }
                }
        }
 
@@ -7103,6 +7124,8 @@ static void intel_crtc_init(struct drm_device *dev, int 
pipe)
        intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
        if (HAS_PCH_SPLIT(dev)) {
+               if (pipe == 2 && IS_IVYBRIDGE(dev))
+                       intel_crtc->no_pll = true;
                intel_helper_funcs.prepare = ironlake_crtc_prepare;
                intel_helper_funcs.commit = ironlake_crtc_commit;
        } else {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0b2ee9d..4b5f543 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -171,6 +171,9 @@ struct intel_crtc {
        int16_t cursor_width, cursor_height;
        bool cursor_visible;
        unsigned int bpp;
+
+       bool no_pll; /* tertiary pipe for IVB */
+       bool use_pll_a;
 };
 
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
b/drivers/gpu/drm/i915/intel_hdmi.c
index 11883c9..ac621dd 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -249,12 +249,10 @@ static void intel_hdmi_mode_set(struct drm_encoder 
*encoder,
                sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
        }
 
-       if (intel_crtc->pipe == 1) {
-               if (HAS_PCH_CPT(dev))
-                       sdvox |= PORT_TRANS_B_SEL_CPT;
-               else
-                       sdvox |= SDVO_PIPE_B_SELECT;
-       }
+       if (HAS_PCH_CPT(dev))
+               sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
+       else if (intel_crtc->pipe == 1)
+               sdvox |= SDVO_PIPE_B_SELECT;
 
        I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
        POSTING_READ(intel_hdmi->sdvox_reg);
-- 
1.7.4.1

Attachment: signature.asc
Description: PGP signature

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

Reply via email to