Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 902daaac authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2016-06-14' of git://anongit.freedesktop.org/drm-intel into drm-fixes

"Pretty much all regression fixes, or black screens."

* tag 'drm-intel-fixes-2016-06-14' of git://anongit.freedesktop.org/drm-intel:
  drm/i915/ilk: Don't disable SSC source if it's in use
  drm/i915: Extract physical display dimensions from VBT
  drm/i915: Check VBT for port presence in addition to the strap on VLV/CHV
  drm/i915: Only ignore eDP ports that are connected
  drm/i915: Silence "unexpected child device config size" for VBT on 845g
  drm/i915: Fix NULL pointer deference when out of PLLs in IVB
parents 27bf60db 476490a9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3481,6 +3481,7 @@ int intel_bios_init(struct drm_i915_private *dev_priv);
bool intel_bios_is_valid_vbt(const void *buf, size_t size);
bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
+45 −1
Original line number Diff line number Diff line
@@ -139,6 +139,11 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
	else
		panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;

	panel_fixed_mode->width_mm = (dvo_timing->himage_hi << 8) |
		dvo_timing->himage_lo;
	panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
		dvo_timing->vimage_lo;

	/* Some VBTs have bogus h/vtotal values */
	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
@@ -1187,7 +1192,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
	}
	if (bdb->version < 106) {
		expected_size = 22;
	} else if (bdb->version < 109) {
	} else if (bdb->version < 111) {
		expected_size = 27;
	} else if (bdb->version < 195) {
		BUILD_BUG_ON(sizeof(struct old_child_dev_config) != 33);
@@ -1545,6 +1550,45 @@ bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin)
	return false;
}

/**
 * intel_bios_is_port_present - is the specified digital port present
 * @dev_priv:	i915 device instance
 * @port:	port to check
 *
 * Return true if the device in %port is present.
 */
bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port)
{
	static const struct {
		u16 dp, hdmi;
	} port_mapping[] = {
		[PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
		[PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
		[PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
		[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
	};
	int i;

	/* FIXME maybe deal with port A as well? */
	if (WARN_ON(port == PORT_A) || port >= ARRAY_SIZE(port_mapping))
		return false;

	if (!dev_priv->vbt.child_dev_num)
		return false;

	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
		const union child_device_config *p_child =
			&dev_priv->vbt.child_dev[i];
		if ((p_child->common.dvo_port == port_mapping[port].dp ||
		     p_child->common.dvo_port == port_mapping[port].hdmi) &&
		    (p_child->common.device_type & (DEVICE_TYPE_TMDS_DVI_SIGNALING |
						    DEVICE_TYPE_DISPLAYPORT_OUTPUT)))
			return true;
	}

	return false;
}

/**
 * intel_bios_is_port_edp - is the device in given port eDP
 * @dev_priv:	i915 device instance
+60 −28
Original line number Diff line number Diff line
@@ -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,6 +8420,9 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
		POSTING_READ(PCH_DREF_CONTROL);
		udelay(200);

		if (!using_ssc_source) {
			DRM_DEBUG_KMS("Disabling SSC source\n");

			/* Turn off the SSC source */
			val &= ~DREF_SSC_SOURCE_MASK;
			val |= DREF_SSC_SOURCE_DISABLE;
@@ -8415,6 +8434,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
			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.
		 */
		if (I915_READ(VLV_HDMIB) & SDVO_DETECTED &&
		    !intel_dp_is_edp(dev, PORT_B))
		 *
		 * 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.
		 */
		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);
+10 −8
Original line number Diff line number Diff line
@@ -5725,8 +5725,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
	if (!fixed_mode && dev_priv->vbt.lfp_lvds_vbt_mode) {
		fixed_mode = drm_mode_duplicate(dev,
					dev_priv->vbt.lfp_lvds_vbt_mode);
		if (fixed_mode)
		if (fixed_mode) {
			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
			connector->display_info.width_mm = fixed_mode->width_mm;
			connector->display_info.height_mm = fixed_mode->height_mm;
		}
	}
	mutex_unlock(&dev->mode_config.mutex);

@@ -5923,9 +5926,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
	return false;
}

void
intel_dp_init(struct drm_device *dev,
	      i915_reg_t output_reg, enum port port)
bool intel_dp_init(struct drm_device *dev,
		   i915_reg_t output_reg,
		   enum port port)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_digital_port *intel_dig_port;
@@ -5935,7 +5938,7 @@ intel_dp_init(struct drm_device *dev,

	intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
	if (!intel_dig_port)
		return;
		return false;

	intel_connector = intel_connector_alloc();
	if (!intel_connector)
@@ -5992,7 +5995,7 @@ intel_dp_init(struct drm_device *dev,
	if (!intel_dp_init_connector(intel_dig_port, intel_connector))
		goto err_init_connector;

	return;
	return true;

err_init_connector:
	drm_encoder_cleanup(encoder);
@@ -6000,8 +6003,7 @@ intel_dp_init(struct drm_device *dev,
	kfree(intel_connector);
err_connector_alloc:
	kfree(intel_dig_port);

	return;
	return false;
}

void intel_dp_mst_suspend(struct drm_device *dev)
+3 −0
Original line number Diff line number Diff line
@@ -366,6 +366,9 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
					     DPLL_ID_PCH_PLL_B);
	}

	if (!pll)
		return NULL;

	/* reference the pll */
	intel_reference_shared_dpll(pll, crtc_state);

Loading