Skip to content

Commit

Permalink
Merge tag 'drm-intel-next-fixes-2015-09-02' of git://anongit.freedesk…
Browse files Browse the repository at this point in the history
…top.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
  • Loading branch information
Dave Airlie committed Sep 4, 2015
2 parents aed160e + 6fa2d19 commit 5b78cb6
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 82 deletions.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2562,6 +2562,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
return "PORT_DDI_D_2_LANES";
case POWER_DOMAIN_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:
return "PORT_DSI";
case POWER_DOMAIN_PORT_CRT:
Expand Down
15 changes: 9 additions & 6 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,15 +662,18 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)

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
* leave the device in D0 on those platforms and hope the BIOS will
* power down the device properly. Platforms where this was seen:
* Lenovo Thinkpad X301, X61s
* power down the device properly. The issue was seen on multiple old
* 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 &&
drm_dev->pdev->subsystem_vendor == PCI_VENDOR_ID_LENOVO &&
INTEL_INFO(dev_priv)->gen == 4))
if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6))
pci_set_power_state(drm_dev->pdev, PCI_D3hot);

return 0;
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_DDI_C_4_LANES,
POWER_DOMAIN_PORT_DDI_D_2_LANES,
POWER_DOMAIN_PORT_DDI_D_4_LANES,
POWER_DOMAIN_PORT_DDI_E_2_LANES,
POWER_DOMAIN_PORT_DSI,
POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_PORT_OTHER,
Expand Down Expand Up @@ -1416,6 +1417,10 @@ enum modeset_restore {
#define DP_AUX_C 0x20
#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 {
/*
* This is an index in the HDMI/DVI DDI buffer translation table.
Expand All @@ -1430,6 +1435,7 @@ struct ddi_vbt_port_info {
uint8_t supports_dp:1;

uint8_t alternate_aux_channel;
uint8_t alternate_ddc_pin;

uint8_t dp_boost_level;
uint8_t hdmi_boost_level;
Expand Down
39 changes: 28 additions & 11 deletions drivers/gpu/drm/i915/intel_bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -905,23 +905,23 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
uint8_t hdmi_level_shift;
int i, j;
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,
* so look for all the possible values for each port and abort if more
* than one is found. */
int dvo_ports[][2] = {
{DVO_PORT_HDMIA, DVO_PORT_DPA},
{DVO_PORT_HDMIB, DVO_PORT_DPB},
{DVO_PORT_HDMIC, DVO_PORT_DPC},
{DVO_PORT_HDMID, DVO_PORT_DPD},
{DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ },
int dvo_ports[][3] = {
{DVO_PORT_HDMIA, DVO_PORT_DPA, -1},
{DVO_PORT_HDMIB, DVO_PORT_DPB, -1},
{DVO_PORT_HDMIC, DVO_PORT_DPC, -1},
{DVO_PORT_HDMID, DVO_PORT_DPD, -1},
{DVO_PORT_CRT, DVO_PORT_HDMIE, DVO_PORT_DPE},
};

/* Find the child device to use, abort if more than one found. */
for (i = 0; i < dev_priv->vbt.child_dev_num; 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)
break;

Expand All @@ -939,6 +939,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
return;

aux_channel = child->raw[25];
ddc_pin = child->common.ddc_pin;

is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
Expand Down Expand Up @@ -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));

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");
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");
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");
}

Expand Down
7 changes: 2 additions & 5 deletions drivers/gpu/drm/i915/intel_bios.h
Original file line number Diff line number Diff line change
Expand Up @@ -758,11 +758,6 @@ int intel_parse_bios(struct drm_device *dev);
#define DVO_C 2
#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: */
#define DVO_PORT_HDMIA 0
#define DVO_PORT_HDMIB 1
Expand All @@ -775,6 +770,8 @@ int intel_parse_bios(struct drm_device *dev);
#define DVO_PORT_DPC 8
#define DVO_PORT_DPD 9
#define DVO_PORT_DPA 10
#define DVO_PORT_DPE 11
#define DVO_PORT_HDMIE 12
#define DVO_PORT_MIPIA 21
#define DVO_PORT_MIPIB 22
#define DVO_PORT_MIPIC 23
Expand Down
11 changes: 4 additions & 7 deletions drivers/gpu/drm/i915/intel_ddi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1554,17 +1554,14 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,
DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
wrpll_params.central_freq;
} else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
struct drm_encoder *encoder = &intel_encoder->base;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);

switch (intel_dp->link_bw) {
case DP_LINK_BW_1_62:
switch (crtc_state->port_clock / 2) {
case 81000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
break;
case DP_LINK_BW_2_7:
case 135000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
break;
case DP_LINK_BW_5_4:
case 270000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
break;
}
Expand Down
54 changes: 34 additions & 20 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -5150,14 +5150,15 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
{
switch (port) {
case PORT_A:
case PORT_E:
return POWER_DOMAIN_PORT_DDI_A_4_LANES;
case PORT_B:
return POWER_DOMAIN_PORT_DDI_B_4_LANES;
case PORT_C:
return POWER_DOMAIN_PORT_DDI_C_4_LANES;
case PORT_D:
return POWER_DOMAIN_PORT_DDI_D_4_LANES;
case PORT_E:
return POWER_DOMAIN_PORT_DDI_E_2_LANES;
default:
WARN_ON_ONCE(1);
return POWER_DOMAIN_PORT_OTHER;
Expand Down Expand Up @@ -5712,16 +5713,13 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
/* enable PG1 and Misc I/O */
intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);

/* DPLL0 already enabed !? */
if (I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE) {
DRM_DEBUG_DRIVER("DPLL0 already running\n");
return;
/* DPLL0 not enabled (happens on early BIOS versions) */
if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) {
/* enable DPLL0 */
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 */
skl_set_cdclk(dev_priv, dev_priv->skl_boot_cdclk);

Expand Down Expand Up @@ -13963,6 +13961,15 @@ static void intel_setup_outputs(struct drm_device *dev)
intel_ddi_init(dev, PORT_C);
if (found & SFUSE_STRAP_DDID_DETECTED)
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)) {
int found;
dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
Expand Down Expand Up @@ -14733,6 +14740,24 @@ void intel_modeset_init(struct drm_device *dev)
if (INTEL_INFO(dev)->num_pipes == 0)
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_audio(dev);

Expand Down Expand Up @@ -15292,7 +15317,6 @@ void intel_display_resume(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_i915_gem_object *obj;
int ret;
Expand All @@ -15301,16 +15325,6 @@ void intel_modeset_gem_init(struct drm_device *dev)
intel_init_gt_powersave(dev);
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_setup_overlay(dev);
Expand Down
Loading

0 comments on commit 5b78cb6

Please sign in to comment.