diff mbox

[2/4] drm/i915/skl: Set the eDP link rate on DPLL0

Message ID 1415985875-7485-3-git-send-email-damien.lespiau@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lespiau, Damien Nov. 14, 2014, 5:24 p.m. UTC
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>
---
 drivers/gpu/drm/i915/intel_ddi.c | 20 ++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c  | 31 ++++++++++++++++++++++++++++++-
 2 files changed, 50 insertions(+), 1 deletion(-)

Comments

Daniel Vetter Nov. 17, 2014, 6:24 p.m. UTC | #1
On Fri, Nov 14, 2014 at 05:24:33PM +0000, Damien Lespiau wrote:
> 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>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c | 20 ++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_dp.c  | 31 ++++++++++++++++++++++++++++++-
>  2 files changed, 50 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index ca33ee9..596bdc1 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -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) {

Are you sure you really want to check for edp here and not for something
more specific like port A? Same with the is_edp check below.

In the past we've had piles of fun with code that checked for is_edp, but
which should have checked for port A or something similar - on desktop
platforms (at least in all chips thus far, dunno about skl) edp ends up on
port D.

Oh and someone bored might want to replace the pile of type == DP || type
== EDP checks in intel_ddi.c with config->has_dp_encoder.

I'll hold off on merging this for now just out of curiosity ;-)
-Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index ca33ee9..596bdc1 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -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);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 45b53ff..5dde84f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1075,6 +1075,33 @@  intel_dp_connector_unregister(struct intel_connector *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)
 {
 	switch (link_bw) {
@@ -1251,7 +1278,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);