drm/i915/skl: Set the eDP link rate on DPLL0
authorDamien Lespiau <damien.lespiau@intel.com>
Fri, 14 Nov 2014 17:24:33 +0000 (17:24 +0000)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 17 Nov 2014 18:19:44 +0000 (19:19 +0100)
On SKL DPLL0 is used to derive CDCLK but can also be used to drive an
eDP port (as long as we don't want SSC). DPLL0 is special enough to not
be handled by the shared DPLL framework (drives CDCLK, not supposed to
enable the HDMI mode), So we need to compute the configuration
separately from the other DPLLs.

Note that we don't need to reprogram DPLL0 (which would mean bringing
down CDCLK) to support the various eDP 1.3 link rates as they all share
the same VCO (8100).

Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_dp.c

index 3e4c63cfa415d92340d337e32114aec7952605b7..83eeecbaa4bb974c5e58a767938c180bd5af3be6 100644 (file)
@@ -1484,6 +1484,25 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
                uint32_t dpll = crtc->config.ddi_pll_sel;
                uint32_t val;
 
+               /*
+                * DPLL0 is used for eDP and is the only "private" DPLL (as
+                * opposed to shared) on SKL
+                */
+               if (type == INTEL_OUTPUT_EDP) {
+                       WARN_ON(dpll != SKL_DPLL0);
+
+                       val = I915_READ(DPLL_CTRL1);
+
+                       val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) |
+                                DPLL_CTRL1_SSC(dpll) |
+                                DPLL_CRTL1_LINK_RATE_MASK(dpll));
+                       val |= crtc->config.dpll_hw_state.ctrl1 << (dpll * 6);
+
+                       I915_WRITE(DPLL_CTRL1, val);
+                       POSTING_READ(DPLL_CTRL1);
+               }
+
+               /* DDI -> PLL mapping  */
                val = I915_READ(DPLL_CTRL2);
 
                val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) |
@@ -1492,6 +1511,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
                        DPLL_CTRL2_DDI_SEL_OVERRIDE(port));
 
                I915_WRITE(DPLL_CTRL2, val);
+
        } else {
                WARN_ON(crtc->config.ddi_pll_sel == PORT_CLK_SEL_NONE);
                I915_WRITE(PORT_CLK_SEL(port), crtc->config.ddi_pll_sel);
index 7369e6f1011780feb92607b53f3c25a17de09494..4e49caa5a1b395e7543986c7f7d59911250fedb6 100644 (file)
@@ -1073,6 +1073,33 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector)
        intel_connector_unregister(intel_connector);
 }
 
+static void
+skl_edp_set_pll_config(struct intel_crtc_config *pipe_config, int link_bw)
+{
+       u32 ctrl1;
+
+       pipe_config->ddi_pll_sel = SKL_DPLL0;
+       pipe_config->dpll_hw_state.cfgcr1 = 0;
+       pipe_config->dpll_hw_state.cfgcr2 = 0;
+
+       ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
+       switch (link_bw) {
+       case DP_LINK_BW_1_62:
+               ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_810,
+                                             SKL_DPLL0);
+               break;
+       case DP_LINK_BW_2_7:
+               ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_1350,
+                                             SKL_DPLL0);
+               break;
+       case DP_LINK_BW_5_4:
+               ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_2700,
+                                             SKL_DPLL0);
+               break;
+       }
+       pipe_config->dpll_hw_state.ctrl1 = ctrl1;
+}
+
 static void
 hsw_dp_set_ddi_pll_sel(struct intel_crtc_config *pipe_config, int link_bw)
 {
@@ -1250,7 +1277,9 @@ found:
                                &pipe_config->dp_m2_n2);
        }
 
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+       if (IS_SKYLAKE(dev) && is_edp(intel_dp))
+               skl_edp_set_pll_config(pipe_config, intel_dp->link_bw);
+       else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw);
        else
                intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);