Commit 5b78cb66 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-fixes-2015-09-02' of...

Merge tag 'drm-intel-next-fixes-2015-09-02' of git://anongit.freedesktop.org/drm-intel into drm-next

i915 display fixes headed for v4.3. Mostly SKL, but some regression
fixes too.

* tag 'drm-intel-next-fixes-2015-09-02' of git://anongit.freedesktop.org/drm-intel:
  i915: Set ddi_pll_sel in DP MST path
  drm/i915: Don't use link_bw for PLL setup
  drm/i915: Preserve SSC earlier
  drm/i915/skl: Adding DDI_E power well domain
  drm/i915: eDP can be present on DDI-E
  drm/i915/skl: Enable DDI-E
  drm/i915: Enable HDMI on DDI-E
  drm/i915: apply the PCI_D0/D3 hibernation workaround everywhere on pre GEN6
  drm/i915: Check DP link status on long hpd too
  drm/i915: set CDCLK if DPLL0 enabled during resuming from S3
parents aed160ea 6fa2d197
...@@ -2562,6 +2562,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain) ...@@ -2562,6 +2562,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
return "PORT_DDI_D_2_LANES"; return "PORT_DDI_D_2_LANES";
case POWER_DOMAIN_PORT_DDI_D_4_LANES: case POWER_DOMAIN_PORT_DDI_D_4_LANES:
return "PORT_DDI_D_4_LANES"; return "PORT_DDI_D_4_LANES";
case POWER_DOMAIN_PORT_DDI_E_2_LANES:
return "PORT_DDI_E_2_LANES";
case POWER_DOMAIN_PORT_DSI: case POWER_DOMAIN_PORT_DSI:
return "PORT_DSI"; return "PORT_DSI";
case POWER_DOMAIN_PORT_CRT: case POWER_DOMAIN_PORT_CRT:
......
...@@ -662,15 +662,18 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) ...@@ -662,15 +662,18 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
pci_disable_device(drm_dev->pdev); pci_disable_device(drm_dev->pdev);
/* /*
* During hibernation on some GEN4 platforms the BIOS may try to access * During hibernation on some platforms the BIOS may try to access
* the device even though it's already in D3 and hang the machine. So * the device even though it's already in D3 and hang the machine. So
* leave the device in D0 on those platforms and hope the BIOS will * leave the device in D0 on those platforms and hope the BIOS will
* power down the device properly. Platforms where this was seen: * power down the device properly. The issue was seen on multiple old
* Lenovo Thinkpad X301, X61s * GENs with different BIOS vendors, so having an explicit blacklist
* is inpractical; apply the workaround on everything pre GEN6. The
* platforms where the issue was seen:
* Lenovo Thinkpad X301, X61s, X60, T60, X41
* Fujitsu FSC S7110
* Acer Aspire 1830T
*/ */
if (!(hibernation && if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6))
drm_dev->pdev->subsystem_vendor == PCI_VENDOR_ID_LENOVO &&
INTEL_INFO(dev_priv)->gen == 4))
pci_set_power_state(drm_dev->pdev, PCI_D3hot); pci_set_power_state(drm_dev->pdev, PCI_D3hot);
return 0; return 0;
......
...@@ -182,6 +182,7 @@ enum intel_display_power_domain { ...@@ -182,6 +182,7 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_DDI_C_4_LANES, POWER_DOMAIN_PORT_DDI_C_4_LANES,
POWER_DOMAIN_PORT_DDI_D_2_LANES, POWER_DOMAIN_PORT_DDI_D_2_LANES,
POWER_DOMAIN_PORT_DDI_D_4_LANES, POWER_DOMAIN_PORT_DDI_D_4_LANES,
POWER_DOMAIN_PORT_DDI_E_2_LANES,
POWER_DOMAIN_PORT_DSI, POWER_DOMAIN_PORT_DSI,
POWER_DOMAIN_PORT_CRT, POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_PORT_OTHER, POWER_DOMAIN_PORT_OTHER,
...@@ -1416,6 +1417,10 @@ enum modeset_restore { ...@@ -1416,6 +1417,10 @@ enum modeset_restore {
#define DP_AUX_C 0x20 #define DP_AUX_C 0x20
#define DP_AUX_D 0x30 #define DP_AUX_D 0x30
#define DDC_PIN_B 0x05
#define DDC_PIN_C 0x04
#define DDC_PIN_D 0x06
struct ddi_vbt_port_info { struct ddi_vbt_port_info {
/* /*
* This is an index in the HDMI/DVI DDI buffer translation table. * This is an index in the HDMI/DVI DDI buffer translation table.
...@@ -1430,6 +1435,7 @@ struct ddi_vbt_port_info { ...@@ -1430,6 +1435,7 @@ struct ddi_vbt_port_info {
uint8_t supports_dp:1; uint8_t supports_dp:1;
uint8_t alternate_aux_channel; uint8_t alternate_aux_channel;
uint8_t alternate_ddc_pin;
uint8_t dp_boost_level; uint8_t dp_boost_level;
uint8_t hdmi_boost_level; uint8_t hdmi_boost_level;
......
...@@ -905,23 +905,23 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, ...@@ -905,23 +905,23 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
uint8_t hdmi_level_shift; uint8_t hdmi_level_shift;
int i, j; int i, j;
bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; bool is_dvi, is_hdmi, is_dp, is_edp, is_crt;
uint8_t aux_channel; uint8_t aux_channel, ddc_pin;
/* Each DDI port can have more than one value on the "DVO Port" field, /* Each DDI port can have more than one value on the "DVO Port" field,
* so look for all the possible values for each port and abort if more * so look for all the possible values for each port and abort if more
* than one is found. */ * than one is found. */
int dvo_ports[][2] = { int dvo_ports[][3] = {
{DVO_PORT_HDMIA, DVO_PORT_DPA}, {DVO_PORT_HDMIA, DVO_PORT_DPA, -1},
{DVO_PORT_HDMIB, DVO_PORT_DPB}, {DVO_PORT_HDMIB, DVO_PORT_DPB, -1},
{DVO_PORT_HDMIC, DVO_PORT_DPC}, {DVO_PORT_HDMIC, DVO_PORT_DPC, -1},
{DVO_PORT_HDMID, DVO_PORT_DPD}, {DVO_PORT_HDMID, DVO_PORT_DPD, -1},
{DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ }, {DVO_PORT_CRT, DVO_PORT_HDMIE, DVO_PORT_DPE},
}; };
/* Find the child device to use, abort if more than one found. */ /* Find the child device to use, abort if more than one found. */
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
it = dev_priv->vbt.child_dev + i; it = dev_priv->vbt.child_dev + i;
for (j = 0; j < 2; j++) { for (j = 0; j < 3; j++) {
if (dvo_ports[port][j] == -1) if (dvo_ports[port][j] == -1)
break; break;
...@@ -939,6 +939,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, ...@@ -939,6 +939,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
return; return;
aux_channel = child->raw[25]; aux_channel = child->raw[25];
ddc_pin = child->common.ddc_pin;
is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
...@@ -970,11 +971,27 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, ...@@ -970,11 +971,27 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port));
if (is_dvi) { if (is_dvi) {
if (child->common.ddc_pin == 0x05 && port != PORT_B) if (port == PORT_E) {
info->alternate_ddc_pin = ddc_pin;
/* if DDIE share ddc pin with other port, then
* dvi/hdmi couldn't exist on the shared port.
* Otherwise they share the same ddc bin and system
* couldn't communicate with them seperately. */
if (ddc_pin == DDC_PIN_B) {
dev_priv->vbt.ddi_port_info[PORT_B].supports_dvi = 0;
dev_priv->vbt.ddi_port_info[PORT_B].supports_hdmi = 0;
} else if (ddc_pin == DDC_PIN_C) {
dev_priv->vbt.ddi_port_info[PORT_C].supports_dvi = 0;
dev_priv->vbt.ddi_port_info[PORT_C].supports_hdmi = 0;
} else if (ddc_pin == DDC_PIN_D) {
dev_priv->vbt.ddi_port_info[PORT_D].supports_dvi = 0;
dev_priv->vbt.ddi_port_info[PORT_D].supports_hdmi = 0;
}
} else if (ddc_pin == DDC_PIN_B && port != PORT_B)
DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); DRM_DEBUG_KMS("Unexpected DDC pin for port B\n");
if (child->common.ddc_pin == 0x04 && port != PORT_C) else if (ddc_pin == DDC_PIN_C && port != PORT_C)
DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); DRM_DEBUG_KMS("Unexpected DDC pin for port C\n");
if (child->common.ddc_pin == 0x06 && port != PORT_D) else if (ddc_pin == DDC_PIN_D && port != PORT_D)
DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); DRM_DEBUG_KMS("Unexpected DDC pin for port D\n");
} }
......
...@@ -758,11 +758,6 @@ int intel_parse_bios(struct drm_device *dev); ...@@ -758,11 +758,6 @@ int intel_parse_bios(struct drm_device *dev);
#define DVO_C 2 #define DVO_C 2
#define DVO_D 3 #define DVO_D 3
/* define the PORT for DP output type */
#define PORT_IDPB 7
#define PORT_IDPC 8
#define PORT_IDPD 9
/* Possible values for the "DVO Port" field for versions >= 155: */ /* Possible values for the "DVO Port" field for versions >= 155: */
#define DVO_PORT_HDMIA 0 #define DVO_PORT_HDMIA 0
#define DVO_PORT_HDMIB 1 #define DVO_PORT_HDMIB 1
...@@ -775,6 +770,8 @@ int intel_parse_bios(struct drm_device *dev); ...@@ -775,6 +770,8 @@ int intel_parse_bios(struct drm_device *dev);
#define DVO_PORT_DPC 8 #define DVO_PORT_DPC 8
#define DVO_PORT_DPD 9 #define DVO_PORT_DPD 9
#define DVO_PORT_DPA 10 #define DVO_PORT_DPA 10
#define DVO_PORT_DPE 11
#define DVO_PORT_HDMIE 12
#define DVO_PORT_MIPIA 21 #define DVO_PORT_MIPIA 21
#define DVO_PORT_MIPIB 22 #define DVO_PORT_MIPIB 22
#define DVO_PORT_MIPIC 23 #define DVO_PORT_MIPIC 23
......
...@@ -1554,17 +1554,14 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, ...@@ -1554,17 +1554,14 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,
DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
wrpll_params.central_freq; wrpll_params.central_freq;
} else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
struct drm_encoder *encoder = &intel_encoder->base; switch (crtc_state->port_clock / 2) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); case 81000:
switch (intel_dp->link_bw) {
case DP_LINK_BW_1_62:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
break; break;
case DP_LINK_BW_2_7: case 135000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0); ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
break; break;
case DP_LINK_BW_5_4: case 270000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
break; break;
} }
......
...@@ -5150,7 +5150,6 @@ static enum intel_display_power_domain port_to_power_domain(enum port port) ...@@ -5150,7 +5150,6 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
{ {
switch (port) { switch (port) {
case PORT_A: case PORT_A:
case PORT_E:
return POWER_DOMAIN_PORT_DDI_A_4_LANES; return POWER_DOMAIN_PORT_DDI_A_4_LANES;
case PORT_B: case PORT_B:
return POWER_DOMAIN_PORT_DDI_B_4_LANES; return POWER_DOMAIN_PORT_DDI_B_4_LANES;
...@@ -5158,6 +5157,8 @@ static enum intel_display_power_domain port_to_power_domain(enum port port) ...@@ -5158,6 +5157,8 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
return POWER_DOMAIN_PORT_DDI_C_4_LANES; return POWER_DOMAIN_PORT_DDI_C_4_LANES;
case PORT_D: case PORT_D:
return POWER_DOMAIN_PORT_DDI_D_4_LANES; return POWER_DOMAIN_PORT_DDI_D_4_LANES;
case PORT_E:
return POWER_DOMAIN_PORT_DDI_E_2_LANES;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return POWER_DOMAIN_PORT_OTHER; return POWER_DOMAIN_PORT_OTHER;
...@@ -5712,16 +5713,13 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) ...@@ -5712,16 +5713,13 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
/* enable PG1 and Misc I/O */ /* enable PG1 and Misc I/O */
intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
/* DPLL0 already enabed !? */ /* DPLL0 not enabled (happens on early BIOS versions) */
if (I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE) { if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) {
DRM_DEBUG_DRIVER("DPLL0 already running\n"); /* enable DPLL0 */
return; required_vco = skl_cdclk_get_vco(dev_priv->skl_boot_cdclk);
skl_dpll0_enable(dev_priv, required_vco);
} }
/* enable DPLL0 */
required_vco = skl_cdclk_get_vco(dev_priv->skl_boot_cdclk);
skl_dpll0_enable(dev_priv, required_vco);
/* set CDCLK to the frequency the BIOS chose */ /* set CDCLK to the frequency the BIOS chose */
skl_set_cdclk(dev_priv, dev_priv->skl_boot_cdclk); skl_set_cdclk(dev_priv, dev_priv->skl_boot_cdclk);
...@@ -13963,6 +13961,15 @@ static void intel_setup_outputs(struct drm_device *dev) ...@@ -13963,6 +13961,15 @@ static void intel_setup_outputs(struct drm_device *dev)
intel_ddi_init(dev, PORT_C); intel_ddi_init(dev, PORT_C);
if (found & SFUSE_STRAP_DDID_DETECTED) if (found & SFUSE_STRAP_DDID_DETECTED)
intel_ddi_init(dev, PORT_D); intel_ddi_init(dev, PORT_D);
/*
* On SKL we don't have a way to detect DDI-E so we rely on VBT.
*/
if (IS_SKYLAKE(dev) &&
(dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
intel_ddi_init(dev, PORT_E);
} else if (HAS_PCH_SPLIT(dev)) { } else if (HAS_PCH_SPLIT(dev)) {
int found; int found;
dpd_is_edp = intel_dp_is_edp(dev, PORT_D); dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
...@@ -14733,6 +14740,24 @@ void intel_modeset_init(struct drm_device *dev) ...@@ -14733,6 +14740,24 @@ void intel_modeset_init(struct drm_device *dev)
if (INTEL_INFO(dev)->num_pipes == 0) if (INTEL_INFO(dev)->num_pipes == 0)
return; return;
/*
* There may be no VBT; and if the BIOS enabled SSC we can
* just keep using it to avoid unnecessary flicker. Whereas if the
* BIOS isn't using it, don't assume it will work even if the VBT
* indicates as much.
*/
if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) &
DREF_SSC1_ENABLE);
if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) {
DRM_DEBUG_KMS("SSC %sabled by BIOS, overriding VBT which says %sabled\n",
bios_lvds_use_ssc ? "en" : "dis",
dev_priv->vbt.lvds_use_ssc ? "en" : "dis");
dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc;
}
}
intel_init_display(dev); intel_init_display(dev);
intel_init_audio(dev); intel_init_audio(dev);
...@@ -15292,7 +15317,6 @@ void intel_display_resume(struct drm_device *dev) ...@@ -15292,7 +15317,6 @@ void intel_display_resume(struct drm_device *dev)
void intel_modeset_gem_init(struct drm_device *dev) void intel_modeset_gem_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *c; struct drm_crtc *c;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
int ret; int ret;
...@@ -15301,16 +15325,6 @@ void intel_modeset_gem_init(struct drm_device *dev) ...@@ -15301,16 +15325,6 @@ void intel_modeset_gem_init(struct drm_device *dev)
intel_init_gt_powersave(dev); intel_init_gt_powersave(dev);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
/*
* There may be no VBT; and if the BIOS enabled SSC we can
* just keep using it to avoid unnecessary flicker. Whereas if the
* BIOS isn't using it, don't assume it will work even if the VBT
* indicates as much.
*/
if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
dev_priv->vbt.lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) &
DREF_SSC1_ENABLE);
intel_modeset_init_hw(dev); intel_modeset_init_hw(dev);
intel_setup_overlay(dev); intel_setup_overlay(dev);
......
...@@ -48,28 +48,28 @@ ...@@ -48,28 +48,28 @@
#define INTEL_DP_RESOLUTION_FAILSAFE (3 << INTEL_DP_RESOLUTION_SHIFT_MASK) #define INTEL_DP_RESOLUTION_FAILSAFE (3 << INTEL_DP_RESOLUTION_SHIFT_MASK)
struct dp_link_dpll { struct dp_link_dpll {
int link_bw; int clock;
struct dpll dpll; struct dpll dpll;
}; };
static const struct dp_link_dpll gen4_dpll[] = { static const struct dp_link_dpll gen4_dpll[] = {
{ DP_LINK_BW_1_62, { 162000,
{ .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } }, { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } },
{ DP_LINK_BW_2_7, { 270000,
{ .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } } { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } }
}; };
static const struct dp_link_dpll pch_dpll[] = { static const struct dp_link_dpll pch_dpll[] = {
{ DP_LINK_BW_1_62, { 162000,
{ .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } }, { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } },
{ DP_LINK_BW_2_7, { 270000,
{ .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } } { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } }
}; };
static const struct dp_link_dpll vlv_dpll[] = { static const struct dp_link_dpll vlv_dpll[] = {
{ DP_LINK_BW_1_62, { 162000,
{ .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } }, { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } },
{ DP_LINK_BW_2_7, { 270000,
{ .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } } { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } }
}; };
...@@ -83,11 +83,11 @@ static const struct dp_link_dpll chv_dpll[] = { ...@@ -83,11 +83,11 @@ static const struct dp_link_dpll chv_dpll[] = {
* m2 is stored in fixed point format using formula below * m2 is stored in fixed point format using formula below
* (m2_int << 22) | m2_fraction * (m2_int << 22) | m2_fraction
*/ */
{ DP_LINK_BW_1_62, /* m2_int = 32, m2_fraction = 1677722 */ { 162000, /* m2_int = 32, m2_fraction = 1677722 */
{ .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } },
{ DP_LINK_BW_2_7, /* m2_int = 27, m2_fraction = 0 */ { 270000, /* m2_int = 27, m2_fraction = 0 */
{ .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },
{ DP_LINK_BW_5_4, /* m2_int = 27, m2_fraction = 0 */ { 540000, /* m2_int = 27, m2_fraction = 0 */
{ .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } } { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }
}; };
...@@ -1130,7 +1130,7 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector) ...@@ -1130,7 +1130,7 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector)
} }
static void static void
skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) skl_edp_set_pll_config(struct intel_crtc_state *pipe_config)
{ {
u32 ctrl1; u32 ctrl1;
...@@ -1142,7 +1142,7 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) ...@@ -1142,7 +1142,7 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)
pipe_config->dpll_hw_state.cfgcr2 = 0; pipe_config->dpll_hw_state.cfgcr2 = 0;
ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0); ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
switch (link_clock / 2) { switch (pipe_config->port_clock / 2) {
case 81000: case 81000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
SKL_DPLL0); SKL_DPLL0);
...@@ -1175,20 +1175,20 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) ...@@ -1175,20 +1175,20 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)
pipe_config->dpll_hw_state.ctrl1 = ctrl1; pipe_config->dpll_hw_state.ctrl1 = ctrl1;
} }
static void void
hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config, int link_bw) hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config)
{ {
memset(&pipe_config->dpll_hw_state, 0, memset(&pipe_config->dpll_hw_state, 0,
sizeof(pipe_config->dpll_hw_state)); sizeof(pipe_config->dpll_hw_state));
switch (link_bw) { switch (pipe_config->port_clock / 2) {
case DP_LINK_BW_1_62: case 81000:
pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
break; break;
case DP_LINK_BW_2_7: case 135000:
pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
break; break;
case DP_LINK_BW_5_4: case 270000:
pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
break; break;
} }
...@@ -1245,7 +1245,7 @@ intel_dp_source_rates(struct drm_device *dev, const int **source_rates) ...@@ -1245,7 +1245,7 @@ intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
static void static void
intel_dp_set_clock(struct intel_encoder *encoder, intel_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config, int link_bw) struct intel_crtc_state *pipe_config)
{ {
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
const struct dp_link_dpll *divisor = NULL; const struct dp_link_dpll *divisor = NULL;
...@@ -1267,7 +1267,7 @@ intel_dp_set_clock(struct intel_encoder *encoder, ...@@ -1267,7 +1267,7 @@ intel_dp_set_clock(struct intel_encoder *encoder,
if (divisor && count) { if (divisor && count) {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (link_bw == divisor[i].link_bw) { if (pipe_config->port_clock == divisor[i].clock) {
pipe_config->dpll = divisor[i].dpll; pipe_config->dpll = divisor[i].dpll;
pipe_config->clock_set = true; pipe_config->clock_set = true;
break; break;
...@@ -1544,13 +1544,13 @@ intel_dp_compute_config(struct intel_encoder *encoder, ...@@ -1544,13 +1544,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
} }
if (IS_SKYLAKE(dev) && is_edp(intel_dp)) if (IS_SKYLAKE(dev) && is_edp(intel_dp))
skl_edp_set_pll_config(pipe_config, common_rates[clock]); skl_edp_set_pll_config(pipe_config);
else if (IS_BROXTON(dev)) else if (IS_BROXTON(dev))
/* handled in ddi */; /* handled in ddi */;
else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw); hsw_dp_set_ddi_pll_sel(pipe_config);
else else
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); intel_dp_set_clock(encoder, pipe_config);
return true; return true;
} }
...@@ -4961,9 +4961,12 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) ...@@ -4961,9 +4961,12 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
intel_dp_probe_oui(intel_dp); intel_dp_probe_oui(intel_dp);
if (!intel_dp_probe_mst(intel_dp)) if (!intel_dp_probe_mst(intel_dp)) {
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
intel_dp_check_link_status(intel_dp);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
goto mst_fail; goto mst_fail;
}
} else { } else {
if (intel_dp->is_mst) { if (intel_dp->is_mst) {
if (intel_dp_check_mst_status(intel_dp) == -EINVAL) if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
...@@ -4971,10 +4974,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) ...@@ -4971,10 +4974,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
} }
if (!intel_dp->is_mst) { if (!intel_dp->is_mst) {
/*
* we'll check the link status via the normal hot plug path later -
* but for short hpds we should check it now
*/
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
intel_dp_check_link_status(intel_dp); intel_dp_check_link_status(intel_dp);
drm_modeset_unlock(&dev->mode_config.connection_mutex); drm_modeset_unlock(&dev->mode_config.connection_mutex);
...@@ -5016,16 +5015,17 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc) ...@@ -5016,16 +5015,17 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
return -1; return -1;
} }
/* check the VBT to see whether the eDP is on DP-D port */ /* check the VBT to see whether the eDP is on another port */
bool intel_dp_is_edp(struct drm_device *dev, enum port port) bool intel_dp_is_edp(struct drm_device *dev, enum port port)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
union child_device_config *p_child; union child_device_config *p_child;
int i; int i;
static const short port_mapping[] = { static const short port_mapping[] = {
[PORT_B] = PORT_IDPB, [PORT_B] = DVO_PORT_DPB,
[PORT_C] = PORT_IDPC, [PORT_C] = DVO_PORT_DPC,
[PORT_D] = PORT_IDPD, [PORT_D] = DVO_PORT_DPD,
[PORT_E] = DVO_PORT_DPE,
}; };
if (port == PORT_A) if (port == PORT_A)
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config) struct intel_crtc_state *pipe_config)
{ {
struct drm_device *dev = encoder->base.dev;
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
struct intel_digital_port *intel_dig_port = intel_mst->primary; struct intel_digital_port *intel_dig_port = intel_mst->primary;
struct intel_dp *intel_dp = &intel_dig_port->dp; struct intel_dp *intel_dp = &intel_dig_port->dp;
...@@ -97,6 +98,10 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, ...@@ -97,6 +98,10 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
&pipe_config->dp_m_n); &pipe_config->dp_m_n);
pipe_config->dp_m_n.tu = slots; pipe_config->dp_m_n.tu = slots;
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
hsw_dp_set_ddi_pll_sel(pipe_config);
return true; return true;
} }
......
...@@ -1185,6 +1185,7 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp); ...@@ -1185,6 +1185,7 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp);
void intel_edp_drrs_invalidate(struct drm_device *dev, void intel_edp_drrs_invalidate(struct drm_device *dev,
unsigned frontbuffer_bits); unsigned frontbuffer_bits);
void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits); void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
/* intel_dp_mst.c */ /* intel_dp_mst.c */
int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
......
...@@ -1958,6 +1958,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -1958,6 +1958,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
struct drm_device *dev = intel_encoder->base.dev; struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_dig_port->port; enum port port = intel_dig_port->port;
uint8_t alternate_ddc_pin;
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA); DRM_MODE_CONNECTOR_HDMIA);
...@@ -1991,6 +1992,26 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -1991,6 +1992,26 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
intel_hdmi->ddc_bus = GMBUS_PIN_DPD; intel_hdmi->ddc_bus = GMBUS_PIN_DPD;
intel_encoder->hpd_pin = HPD_PORT_D; intel_encoder->hpd_pin = HPD_PORT_D;
break; break;
case PORT_E:
/* On SKL PORT E doesn't have seperate GMBUS pin
* We rely on VBT to set a proper alternate GMBUS pin. */
alternate_ddc_pin =
dev_priv->vbt.ddi_port_info[PORT_E].alternate_ddc_pin;
switch (alternate_ddc_pin) {
case DDC_PIN_B:
intel_hdmi->ddc_bus = GMBUS_PIN_DPB;
break;
case DDC_PIN_C:
intel_hdmi->ddc_bus = GMBUS_PIN_DPC;
break;
case DDC_PIN_D:
intel_hdmi->ddc_bus = GMBUS_PIN_DPD;
break;
default:
MISSING_CASE(alternate_ddc_pin);
}
intel_encoder->hpd_pin = HPD_PORT_E;
break;
case PORT_A: case PORT_A:
intel_encoder->hpd_pin = HPD_PORT_A; intel_encoder->hpd_pin = HPD_PORT_A;
/* Internal port only for eDP. */ /* Internal port only for eDP. */
......
...@@ -297,6 +297,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, ...@@ -297,6 +297,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_E_2_LANES) | \
BIT(POWER_DOMAIN_AUX_B) | \ BIT(POWER_DOMAIN_AUX_B) | \
BIT(POWER_DOMAIN_AUX_C) | \ BIT(POWER_DOMAIN_AUX_C) | \
BIT(POWER_DOMAIN_AUX_D) | \ BIT(POWER_DOMAIN_AUX_D) | \
...@@ -316,6 +317,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, ...@@ -316,6 +317,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
#define SKL_DISPLAY_DDI_A_E_POWER_DOMAINS ( \ #define SKL_DISPLAY_DDI_A_E_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_E_2_LANES) | \
BIT(POWER_DOMAIN_INIT)) BIT(POWER_DOMAIN_INIT))
#define SKL_DISPLAY_DDI_B_POWER_DOMAINS ( \ #define SKL_DISPLAY_DDI_B_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
......
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