|
@@ -8275,12 +8275,14 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_encoder *encoder;
|
|
|
+ int i;
|
|
|
u32 val, final;
|
|
|
bool has_lvds = false;
|
|
|
bool has_cpu_edp = false;
|
|
|
bool has_panel = false;
|
|
|
bool has_ck505 = false;
|
|
|
bool can_ssc = false;
|
|
|
+ bool using_ssc_source = false;
|
|
|
|
|
|
/* We need to take the global config into account */
|
|
|
for_each_intel_encoder(dev, encoder) {
|
|
@@ -8307,8 +8309,22 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
|
|
|
can_ssc = true;
|
|
|
}
|
|
|
|
|
|
- DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
|
|
|
- has_panel, has_lvds, has_ck505);
|
|
|
+ /* Check if any DPLLs are using the SSC source */
|
|
|
+ for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
|
|
+ u32 temp = I915_READ(PCH_DPLL(i));
|
|
|
+
|
|
|
+ if (!(temp & DPLL_VCO_ENABLE))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if ((temp & PLL_REF_INPUT_MASK) ==
|
|
|
+ PLLB_REF_INPUT_SPREADSPECTRUMIN) {
|
|
|
+ using_ssc_source = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
|
|
|
+ has_panel, has_lvds, has_ck505, using_ssc_source);
|
|
|
|
|
|
/* Ironlake: try to setup display ref clock before DPLL
|
|
|
* enabling. This is only under driver's control after
|
|
@@ -8345,9 +8361,9 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
|
|
|
final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
|
|
|
} else
|
|
|
final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
|
|
- } else {
|
|
|
- final |= DREF_SSC_SOURCE_DISABLE;
|
|
|
- final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
|
|
|
+ } else if (using_ssc_source) {
|
|
|
+ final |= DREF_SSC_SOURCE_ENABLE;
|
|
|
+ final |= DREF_SSC1_ENABLE;
|
|
|
}
|
|
|
|
|
|
if (final == val)
|
|
@@ -8393,7 +8409,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
udelay(200);
|
|
|
} else {
|
|
|
- DRM_DEBUG_KMS("Disabling SSC entirely\n");
|
|
|
+ DRM_DEBUG_KMS("Disabling CPU source output\n");
|
|
|
|
|
|
val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
|
|
|
|
@@ -8404,16 +8420,20 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
|
|
|
POSTING_READ(PCH_DREF_CONTROL);
|
|
|
udelay(200);
|
|
|
|
|
|
- /* Turn off the SSC source */
|
|
|
- val &= ~DREF_SSC_SOURCE_MASK;
|
|
|
- val |= DREF_SSC_SOURCE_DISABLE;
|
|
|
+ if (!using_ssc_source) {
|
|
|
+ DRM_DEBUG_KMS("Disabling SSC source\n");
|
|
|
|
|
|
- /* Turn off SSC1 */
|
|
|
- val &= ~DREF_SSC1_ENABLE;
|
|
|
+ /* Turn off the SSC source */
|
|
|
+ val &= ~DREF_SSC_SOURCE_MASK;
|
|
|
+ val |= DREF_SSC_SOURCE_DISABLE;
|
|
|
|
|
|
- I915_WRITE(PCH_DREF_CONTROL, val);
|
|
|
- POSTING_READ(PCH_DREF_CONTROL);
|
|
|
- udelay(200);
|
|
|
+ /* Turn off SSC1 */
|
|
|
+ val &= ~DREF_SSC1_ENABLE;
|
|
|
+
|
|
|
+ I915_WRITE(PCH_DREF_CONTROL, val);
|
|
|
+ POSTING_READ(PCH_DREF_CONTROL);
|
|
|
+ udelay(200);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
BUG_ON(val != final);
|
|
@@ -14554,6 +14574,8 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|
|
if (I915_READ(PCH_DP_D) & DP_DETECTED)
|
|
|
intel_dp_init(dev, PCH_DP_D, PORT_D);
|
|
|
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
|
|
+ bool has_edp, has_port;
|
|
|
+
|
|
|
/*
|
|
|
* The DP_DETECTED bit is the latched state of the DDC
|
|
|
* SDA pin at boot. However since eDP doesn't require DDC
|
|
@@ -14562,27 +14584,37 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|
|
* Thus we can't rely on the DP_DETECTED bit alone to detect
|
|
|
* eDP ports. Consult the VBT as well as DP_DETECTED to
|
|
|
* detect eDP ports.
|
|
|
+ *
|
|
|
+ * Sadly the straps seem to be missing sometimes even for HDMI
|
|
|
+ * ports (eg. on Voyo V3 - CHT x7-Z8700), so check both strap
|
|
|
+ * and VBT for the presence of the port. Additionally we can't
|
|
|
+ * trust the port type the VBT declares as we've seen at least
|
|
|
+ * HDMI ports that the VBT claim are DP or eDP.
|
|
|
*/
|
|
|
- if (I915_READ(VLV_HDMIB) & SDVO_DETECTED &&
|
|
|
- !intel_dp_is_edp(dev, PORT_B))
|
|
|
+ has_edp = intel_dp_is_edp(dev, PORT_B);
|
|
|
+ has_port = intel_bios_is_port_present(dev_priv, PORT_B);
|
|
|
+ if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port)
|
|
|
+ has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B);
|
|
|
+ if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
|
|
|
intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
|
|
|
- if (I915_READ(VLV_DP_B) & DP_DETECTED ||
|
|
|
- intel_dp_is_edp(dev, PORT_B))
|
|
|
- intel_dp_init(dev, VLV_DP_B, PORT_B);
|
|
|
|
|
|
- if (I915_READ(VLV_HDMIC) & SDVO_DETECTED &&
|
|
|
- !intel_dp_is_edp(dev, PORT_C))
|
|
|
+ has_edp = intel_dp_is_edp(dev, PORT_C);
|
|
|
+ has_port = intel_bios_is_port_present(dev_priv, PORT_C);
|
|
|
+ if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port)
|
|
|
+ has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C);
|
|
|
+ if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp)
|
|
|
intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
|
|
|
- if (I915_READ(VLV_DP_C) & DP_DETECTED ||
|
|
|
- intel_dp_is_edp(dev, PORT_C))
|
|
|
- intel_dp_init(dev, VLV_DP_C, PORT_C);
|
|
|
|
|
|
if (IS_CHERRYVIEW(dev)) {
|
|
|
- /* eDP not supported on port D, so don't check VBT */
|
|
|
- if (I915_READ(CHV_HDMID) & SDVO_DETECTED)
|
|
|
- intel_hdmi_init(dev, CHV_HDMID, PORT_D);
|
|
|
- if (I915_READ(CHV_DP_D) & DP_DETECTED)
|
|
|
+ /*
|
|
|
+ * eDP not supported on port D,
|
|
|
+ * so no need to worry about it
|
|
|
+ */
|
|
|
+ has_port = intel_bios_is_port_present(dev_priv, PORT_D);
|
|
|
+ if (I915_READ(CHV_DP_D) & DP_DETECTED || has_port)
|
|
|
intel_dp_init(dev, CHV_DP_D, PORT_D);
|
|
|
+ if (I915_READ(CHV_HDMID) & SDVO_DETECTED || has_port)
|
|
|
+ intel_hdmi_init(dev, CHV_HDMID, PORT_D);
|
|
|
}
|
|
|
|
|
|
intel_dsi_init(dev);
|