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

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
...@@ -3481,6 +3481,7 @@ int intel_bios_init(struct drm_i915_private *dev_priv); ...@@ -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_valid_vbt(const void *buf, size_t size);
bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); 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_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_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_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); bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
......
...@@ -139,6 +139,11 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, ...@@ -139,6 +139,11 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
else else
panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC; 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 */ /* Some VBTs have bogus h/vtotal values */
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
...@@ -1187,7 +1192,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, ...@@ -1187,7 +1192,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
} }
if (bdb->version < 106) { if (bdb->version < 106) {
expected_size = 22; expected_size = 22;
} else if (bdb->version < 109) { } else if (bdb->version < 111) {
expected_size = 27; expected_size = 27;
} else if (bdb->version < 195) { } else if (bdb->version < 195) {
BUILD_BUG_ON(sizeof(struct old_child_dev_config) != 33); 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) ...@@ -1545,6 +1550,45 @@ bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin)
return false; 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 * intel_bios_is_port_edp - is the device in given port eDP
* @dev_priv: i915 device instance * @dev_priv: i915 device instance
......
...@@ -8275,12 +8275,14 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) ...@@ -8275,12 +8275,14 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *encoder; struct intel_encoder *encoder;
int i;
u32 val, final; u32 val, final;
bool has_lvds = false; bool has_lvds = false;
bool has_cpu_edp = false; bool has_cpu_edp = false;
bool has_panel = false; bool has_panel = false;
bool has_ck505 = false; bool has_ck505 = false;
bool can_ssc = false; bool can_ssc = false;
bool using_ssc_source = false;
/* We need to take the global config into account */ /* We need to take the global config into account */
for_each_intel_encoder(dev, encoder) { for_each_intel_encoder(dev, encoder) {
...@@ -8307,8 +8309,22 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) ...@@ -8307,8 +8309,22 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
can_ssc = true; can_ssc = true;
} }
DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n", /* Check if any DPLLs are using the SSC source */
has_panel, has_lvds, has_ck505); 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 /* Ironlake: try to setup display ref clock before DPLL
* enabling. This is only under driver's control after * enabling. This is only under driver's control after
...@@ -8345,9 +8361,9 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) ...@@ -8345,9 +8361,9 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
} else } else
final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
} else { } else if (using_ssc_source) {
final |= DREF_SSC_SOURCE_DISABLE; final |= DREF_SSC_SOURCE_ENABLE;
final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; final |= DREF_SSC1_ENABLE;
} }
if (final == val) if (final == val)
...@@ -8393,7 +8409,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) ...@@ -8393,7 +8409,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
POSTING_READ(PCH_DREF_CONTROL); POSTING_READ(PCH_DREF_CONTROL);
udelay(200); udelay(200);
} else { } else {
DRM_DEBUG_KMS("Disabling SSC entirely\n"); DRM_DEBUG_KMS("Disabling CPU source output\n");
val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
...@@ -8404,16 +8420,20 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) ...@@ -8404,16 +8420,20 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
POSTING_READ(PCH_DREF_CONTROL); POSTING_READ(PCH_DREF_CONTROL);
udelay(200); udelay(200);
/* Turn off the SSC source */ if (!using_ssc_source) {
val &= ~DREF_SSC_SOURCE_MASK; DRM_DEBUG_KMS("Disabling SSC source\n");
val |= DREF_SSC_SOURCE_DISABLE;
/* Turn off SSC1 */ /* Turn off the SSC source */
val &= ~DREF_SSC1_ENABLE; val &= ~DREF_SSC_SOURCE_MASK;
val |= DREF_SSC_SOURCE_DISABLE;
I915_WRITE(PCH_DREF_CONTROL, val); /* Turn off SSC1 */
POSTING_READ(PCH_DREF_CONTROL); val &= ~DREF_SSC1_ENABLE;
udelay(200);
I915_WRITE(PCH_DREF_CONTROL, val);
POSTING_READ(PCH_DREF_CONTROL);
udelay(200);
}
} }
BUG_ON(val != final); BUG_ON(val != final);
...@@ -14554,6 +14574,8 @@ static void intel_setup_outputs(struct drm_device *dev) ...@@ -14554,6 +14574,8 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(PCH_DP_D) & DP_DETECTED) if (I915_READ(PCH_DP_D) & DP_DETECTED)
intel_dp_init(dev, PCH_DP_D, PORT_D); intel_dp_init(dev, PCH_DP_D, PORT_D);
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
bool has_edp, has_port;
/* /*
* The DP_DETECTED bit is the latched state of the DDC * The DP_DETECTED bit is the latched state of the DDC
* SDA pin at boot. However since eDP doesn't require 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) ...@@ -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 * Thus we can't rely on the DP_DETECTED bit alone to detect
* eDP ports. Consult the VBT as well as DP_DETECTED to * eDP ports. Consult the VBT as well as DP_DETECTED to
* detect eDP ports. * 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 && has_edp = intel_dp_is_edp(dev, PORT_B);
!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); 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 && has_edp = intel_dp_is_edp(dev, PORT_C);
!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); 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)) { if (IS_CHERRYVIEW(dev)) {
/* eDP not supported on port D, so don't check VBT */ /*
if (I915_READ(CHV_HDMID) & SDVO_DETECTED) * eDP not supported on port D,
intel_hdmi_init(dev, CHV_HDMID, PORT_D); * so no need to worry about it
if (I915_READ(CHV_DP_D) & DP_DETECTED) */
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); 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); intel_dsi_init(dev);
......
...@@ -5725,8 +5725,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, ...@@ -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) { if (!fixed_mode && dev_priv->vbt.lfp_lvds_vbt_mode) {
fixed_mode = drm_mode_duplicate(dev, fixed_mode = drm_mode_duplicate(dev,
dev_priv->vbt.lfp_lvds_vbt_mode); dev_priv->vbt.lfp_lvds_vbt_mode);
if (fixed_mode) if (fixed_mode) {
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; 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); mutex_unlock(&dev->mode_config.mutex);
...@@ -5923,9 +5926,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -5923,9 +5926,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
return false; return false;
} }
void bool intel_dp_init(struct drm_device *dev,
intel_dp_init(struct drm_device *dev, i915_reg_t output_reg,
i915_reg_t output_reg, enum port port) enum port port)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_digital_port *intel_dig_port; struct intel_digital_port *intel_dig_port;
...@@ -5935,7 +5938,7 @@ intel_dp_init(struct drm_device *dev, ...@@ -5935,7 +5938,7 @@ intel_dp_init(struct drm_device *dev,
intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port) if (!intel_dig_port)
return; return false;
intel_connector = intel_connector_alloc(); intel_connector = intel_connector_alloc();
if (!intel_connector) if (!intel_connector)
...@@ -5992,7 +5995,7 @@ intel_dp_init(struct drm_device *dev, ...@@ -5992,7 +5995,7 @@ intel_dp_init(struct drm_device *dev,
if (!intel_dp_init_connector(intel_dig_port, intel_connector)) if (!intel_dp_init_connector(intel_dig_port, intel_connector))
goto err_init_connector; goto err_init_connector;
return; return true;
err_init_connector: err_init_connector:
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
...@@ -6000,8 +6003,7 @@ intel_dp_init(struct drm_device *dev, ...@@ -6000,8 +6003,7 @@ intel_dp_init(struct drm_device *dev,
kfree(intel_connector); kfree(intel_connector);
err_connector_alloc: err_connector_alloc:
kfree(intel_dig_port); kfree(intel_dig_port);
return false;
return;
} }
void intel_dp_mst_suspend(struct drm_device *dev) void intel_dp_mst_suspend(struct drm_device *dev)
......
...@@ -366,6 +366,9 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, ...@@ -366,6 +366,9 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
DPLL_ID_PCH_PLL_B); DPLL_ID_PCH_PLL_B);
} }
if (!pll)
return NULL;
/* reference the pll */ /* reference the pll */
intel_reference_shared_dpll(pll, crtc_state); intel_reference_shared_dpll(pll, crtc_state);
......
...@@ -1284,7 +1284,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private *); ...@@ -1284,7 +1284,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private *);
void intel_csr_ucode_resume(struct drm_i915_private *); void intel_csr_ucode_resume(struct drm_i915_private *);
/* intel_dp.c */ /* intel_dp.c */
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);
bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector); struct intel_connector *intel_connector);
void intel_dp_set_link_params(struct intel_dp *intel_dp, void intel_dp_set_link_params(struct intel_dp *intel_dp,
......
...@@ -1545,6 +1545,9 @@ void intel_dsi_init(struct drm_device *dev) ...@@ -1545,6 +1545,9 @@ void intel_dsi_init(struct drm_device *dev)
goto err; goto err;
} }
connector->display_info.width_mm = fixed_mode->width_mm;
connector->display_info.height_mm = fixed_mode->height_mm;
intel_panel_init(&intel_connector->panel, fixed_mode, NULL); intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
intel_dsi_add_properties(intel_connector); intel_dsi_add_properties(intel_connector);
......
...@@ -2142,6 +2142,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -2142,6 +2142,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
enum port port = intel_dig_port->port; enum port port = intel_dig_port->port;
uint8_t alternate_ddc_pin; uint8_t alternate_ddc_pin;
DRM_DEBUG_KMS("Adding HDMI connector on port %c\n",
port_name(port));
if (WARN(intel_dig_port->max_lanes < 4, if (WARN(intel_dig_port->max_lanes < 4,
"Not enough lanes (%d) for HDMI on port %c\n", "Not enough lanes (%d) for HDMI on port %c\n",
intel_dig_port->max_lanes, port_name(port))) intel_dig_port->max_lanes, port_name(port)))
......
...@@ -1082,6 +1082,8 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -1082,6 +1082,8 @@ void intel_lvds_init(struct drm_device *dev)
fixed_mode = drm_mode_duplicate(dev, 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; 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;
goto out; goto out;
} }
} }
......
...@@ -403,9 +403,10 @@ struct lvds_dvo_timing { ...@@ -403,9 +403,10 @@ struct lvds_dvo_timing {
u8 vsync_off:4; u8 vsync_off:4;
u8 rsvd0:6; u8 rsvd0:6;
u8 hsync_off_hi:2; u8 hsync_off_hi:2;
u8 h_image; u8 himage_lo;
u8 v_image; u8 vimage_lo;
u8 max_hv; u8 vimage_hi:4;
u8 himage_hi:4;
u8 h_border; u8 h_border;
u8 v_border; u8 v_border;
u8 rsvd1:3; u8 rsvd1:3;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment