diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 306 |
1 files changed, 188 insertions, 118 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index dcd336bcdfe7..9eafa191cee2 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -113,17 +113,18 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type) } } -static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type, - enum transcoder cpu_transcoder, - struct drm_i915_private *dev_priv) +static u32 hsw_dip_data_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder, + enum hdmi_infoframe_type type, + int i) { switch (type) { case HDMI_INFOFRAME_TYPE_AVI: - return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder); + return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_SPD: - return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder); + return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_VENDOR: - return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder); + return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i); default: DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); return 0; @@ -365,14 +366,13 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder); + enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; + u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); u32 data_reg; int i; u32 val = I915_READ(ctl_reg); - data_reg = hsw_infoframe_data_reg(type, - intel_crtc->config->cpu_transcoder, - dev_priv); + data_reg = hsw_dip_data_reg(dev_priv, cpu_transcoder, type, 0); if (data_reg == 0) return; @@ -381,12 +381,14 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, mmiowb(); for (i = 0; i < len; i += 4) { - I915_WRITE(data_reg + i, *data); + I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder, + type, i >> 2), *data); data++; } /* Write every possible data byte to force correct ECC calculation. */ for (; i < VIDEO_DIP_DATA_SIZE; i += 4) - I915_WRITE(data_reg + i, 0); + I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder, + type, i >> 2), 0); mmiowb(); val |= hsw_infoframe_enable(type); @@ -447,16 +449,13 @@ static void intel_write_infoframe(struct drm_encoder *encoder, } static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *adjusted_mode) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); union hdmi_infoframe frame; int ret; - /* Set user selected PAR to incoming mode's member */ - adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio; - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, adjusted_mode); if (ret < 0) { @@ -494,7 +493,7 @@ static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) static void intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *adjusted_mode) { union hdmi_infoframe frame; int ret; @@ -509,7 +508,7 @@ intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder, static void g4x_set_infoframes(struct drm_encoder *encoder, bool enable, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); @@ -661,7 +660,7 @@ static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder) static void ibx_set_infoframes(struct drm_encoder *encoder, bool enable, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); @@ -713,7 +712,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, static void cpt_set_infoframes(struct drm_encoder *encoder, bool enable, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); @@ -755,7 +754,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder, static void vlv_set_infoframes(struct drm_encoder *encoder, bool enable, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); @@ -807,7 +806,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, static void hsw_set_infoframes(struct drm_encoder *encoder, bool enable, - struct drm_display_mode *adjusted_mode) + const struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); @@ -844,12 +843,12 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); - struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; u32 hdmi_val; hdmi_val = SDVO_ENCODING_HDMI; - if (!HAS_PCH_SPLIT(dev)) - hdmi_val |= intel_hdmi->color_range; + if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) + hdmi_val |= HDMI_COLOR_RANGE_16_235; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -1260,11 +1259,12 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, if (intel_hdmi->color_range_auto) { /* See CEA-861-E - 5.1 Default Encoding Parameters */ - if (pipe_config->has_hdmi_sink && - drm_match_cea_mode(adjusted_mode) > 1) - intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; - else - intel_hdmi->color_range = 0; + pipe_config->limited_color_range = + pipe_config->has_hdmi_sink && + drm_match_cea_mode(adjusted_mode) > 1; + } else { + pipe_config->limited_color_range = + intel_hdmi->limited_color_range; } if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) { @@ -1273,9 +1273,6 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, clock_12bpc *= 2; } - if (intel_hdmi->color_range) - pipe_config->limited_color_range = true; - if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) pipe_config->has_pch_encoder = true; @@ -1314,6 +1311,9 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, return false; } + /* Set user selected PAR to incoming mode's member */ + adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio; + return true; } @@ -1331,22 +1331,23 @@ intel_hdmi_unset_edid(struct drm_connector *connector) } static bool -intel_hdmi_set_edid(struct drm_connector *connector) +intel_hdmi_set_edid(struct drm_connector *connector, bool force) { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct intel_encoder *intel_encoder = &hdmi_to_dig_port(intel_hdmi)->base; enum intel_display_power_domain power_domain; - struct edid *edid; + struct edid *edid = NULL; bool connected = false; power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); - edid = drm_get_edid(connector, - intel_gmbus_get_adapter(dev_priv, - intel_hdmi->ddc_bus)); + if (force) + edid = drm_get_edid(connector, + intel_gmbus_get_adapter(dev_priv, + intel_hdmi->ddc_bus)); intel_display_power_put(dev_priv, power_domain); @@ -1374,13 +1375,26 @@ static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { enum drm_connector_status status; + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + struct drm_i915_private *dev_priv = to_i915(connector->dev); + bool live_status = false; + unsigned int retry = 3; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + while (!live_status && --retry) { + live_status = intel_digital_port_connected(dev_priv, + hdmi_to_dig_port(intel_hdmi)); + mdelay(10); + } + + if (!live_status) + DRM_DEBUG_KMS("Live status not up!"); + intel_hdmi_unset_edid(connector); - if (intel_hdmi_set_edid(connector)) { + if (intel_hdmi_set_edid(connector, live_status)) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; @@ -1404,7 +1418,7 @@ intel_hdmi_force(struct drm_connector *connector) if (connector->status != connector_status_connected) return; - intel_hdmi_set_edid(connector); + intel_hdmi_set_edid(connector, true); hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; } @@ -1470,7 +1484,7 @@ intel_hdmi_set_property(struct drm_connector *connector, if (property == dev_priv->broadcast_rgb_property) { bool old_auto = intel_hdmi->color_range_auto; - uint32_t old_range = intel_hdmi->color_range; + bool old_range = intel_hdmi->limited_color_range; switch (val) { case INTEL_BROADCAST_RGB_AUTO: @@ -1478,18 +1492,18 @@ intel_hdmi_set_property(struct drm_connector *connector, break; case INTEL_BROADCAST_RGB_FULL: intel_hdmi->color_range_auto = false; - intel_hdmi->color_range = 0; + intel_hdmi->limited_color_range = false; break; case INTEL_BROADCAST_RGB_LIMITED: intel_hdmi->color_range_auto = false; - intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; + intel_hdmi->limited_color_range = true; break; default: return -EINVAL; } if (old_auto == intel_hdmi->color_range_auto && - old_range == intel_hdmi->color_range) + old_range == intel_hdmi->limited_color_range) return 0; goto done; @@ -1525,8 +1539,7 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - struct drm_display_mode *adjusted_mode = - &intel_crtc->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; intel_hdmi_prepare(encoder); @@ -1543,8 +1556,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - struct drm_display_mode *adjusted_mode = - &intel_crtc->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; enum dpio_channel port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; u32 val; @@ -1617,6 +1629,50 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } +static void chv_data_lane_soft_reset(struct intel_encoder *encoder, + bool reset) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); + enum pipe pipe = crtc->pipe; + uint32_t val; + + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); + if (reset) + val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); + else + val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); + + if (crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); + if (reset) + val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); + else + val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + } + + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); + val |= CHV_PCS_REQ_SOFTRESET_EN; + if (reset) + val &= ~DPIO_PCS_CLK_SOFT_RESET; + else + val |= DPIO_PCS_CLK_SOFT_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); + + if (crtc->config->lane_count > 2) { + val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); + val |= CHV_PCS_REQ_SOFTRESET_EN; + if (reset) + val &= ~DPIO_PCS_CLK_SOFT_RESET; + else + val |= DPIO_PCS_CLK_SOFT_RESET; + vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); + } +} + static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); @@ -1630,8 +1686,21 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) intel_hdmi_prepare(encoder); + /* + * Must trick the second common lane into life. + * Otherwise we can't even access the PLL. + */ + if (ch == DPIO_CH0 && pipe == PIPE_B) + dport->release_cl2_override = + !chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true); + + chv_phy_powergate_lanes(encoder, true, 0x0); + mutex_lock(&dev_priv->sb_lock); + /* Assert data lane reset */ + chv_data_lane_soft_reset(encoder, true); + /* program left/right clock distribution */ if (pipe != PIPE_B) { val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); @@ -1683,6 +1752,39 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } +static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe; + u32 val; + + mutex_lock(&dev_priv->sb_lock); + + /* disable left/right clock distribution */ + if (pipe != PIPE_B) { + val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); + val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); + vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val); + } else { + val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1); + val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); + vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val); + } + + mutex_unlock(&dev_priv->sb_lock); + + /* + * Leave the power down bit cleared for at least one + * lane so that chv_powergate_phy_ch() will power + * on something when the channel is otherwise unused. + * When the port is off and the override is removed + * the lanes power down anyway, so otherwise it doesn't + * really matter what the state of power down bits is + * after this. + */ + chv_phy_powergate_lanes(encoder, false, 0x0); +} + static void vlv_hdmi_post_disable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); @@ -1701,33 +1803,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder) static void chv_hdmi_post_disable(struct intel_encoder *encoder) { - struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = - to_intel_crtc(encoder->base.crtc); - enum dpio_channel ch = vlv_dport_to_channel(dport); - enum pipe pipe = intel_crtc->pipe; - u32 val; mutex_lock(&dev_priv->sb_lock); - /* Propagate soft reset to data lane reset */ - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); - val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); - val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); + /* Assert data lane reset */ + chv_data_lane_soft_reset(encoder, true); mutex_unlock(&dev_priv->sb_lock); } @@ -1740,8 +1822,7 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - struct drm_display_mode *adjusted_mode = - &intel_crtc->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; enum dpio_channel ch = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; int data, i, stagger; @@ -1758,23 +1839,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) val &= ~DPIO_LANEDESKEW_STRAP_OVRD; vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); - /* Deassert soft data lane reset*/ - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); - val |= CHV_PCS_REQ_SOFTRESET_EN; - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); - val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); - - val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); - val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); - /* Program Tx latency optimal setting */ for (i = 0; i < 4; i++) { /* Set the upar bit */ @@ -1817,6 +1881,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) DPIO_TX1_STAGGER_MULT(7) | DPIO_TX2_STAGGER_MULT(5)); + /* Deassert data lane reset */ + chv_data_lane_soft_reset(encoder, false); + /* Clear calc init */ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); @@ -1851,31 +1918,33 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) for (i = 0; i < 4; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); + val &= ~DPIO_SWING_MARGIN000_MASK; val |= 102 << DPIO_SWING_MARGIN000_SHIFT; + + /* + * Supposedly this value shouldn't matter when unique transition + * scale is disabled, but in fact it does matter. Let's just + * always program the same value and hope it's OK. + */ + val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT); + val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT; + vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); } - /* Disable unique transition scale */ + /* + * The document said it needs to set bit 27 for ch0 and bit 26 + * for ch1. Might be a typo in the doc. + * For now, for this unique transition scale selection, set bit + * 27 for ch0 and ch1. + */ for (i = 0; i < 4; i++) { val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i)); val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val); } - /* Additional steps for 1200mV-0dB */ -#if 0 - val = vlv_dpio_read(dev_priv, pipe, VLV_TX_DW3(ch)); - if (ch) - val |= DPIO_TX_UNIQ_TRANS_SCALE_CH1; - else - val |= DPIO_TX_UNIQ_TRANS_SCALE_CH0; - vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(ch), val); - - vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(ch), - vlv_dpio_read(dev_priv, pipe, VLV_TX_DW2(ch)) | - (0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT)); -#endif /* Start swing calculation */ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; @@ -1885,11 +1954,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); - /* LRC Bypass */ - val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30); - val |= DPIO_LRC_BYPASS; - vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, val); - mutex_unlock(&dev_priv->sb_lock); intel_hdmi->set_infoframes(&encoder->base, @@ -1899,6 +1963,12 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) g4x_enable_hdmi(encoder); vlv_wait_port_ready(dev_priv, dport, 0x0); + + /* Second common lane will stay alive on its own now */ + if (dport->release_cl2_override) { + chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false); + dport->release_cl2_override = false; + } } static void intel_hdmi_destroy(struct drm_connector *connector) @@ -1931,15 +2001,6 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { }; static void -intel_attach_aspect_ratio_property(struct drm_connector *connector) -{ - if (!drm_mode_create_aspect_ratio_property(connector->dev)) - drm_object_attach_property(&connector->base, - connector->dev->mode_config.aspect_ratio_property, - DRM_MODE_PICTURE_ASPECT_NONE); -} - -static void intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) { intel_attach_force_audio_property(connector); @@ -1974,7 +2035,14 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT; else intel_hdmi->ddc_bus = GMBUS_PIN_DPB; - intel_encoder->hpd_pin = HPD_PORT_B; + /* + * On BXT A0/A1, sw needs to activate DDIA HPD logic and + * interrupts to check the external panel connection. + */ + if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)) + intel_encoder->hpd_pin = HPD_PORT_A; + else + intel_encoder->hpd_pin = HPD_PORT_B; break; case PORT_C: if (IS_BROXTON(dev_priv)) @@ -2051,6 +2119,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_connector_attach_encoder(intel_connector, intel_encoder); drm_connector_register(connector); + intel_hdmi->attached_connector = intel_connector; /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written * 0xd. Failure to do so will result in spurious interrupts being @@ -2097,6 +2166,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) intel_encoder->pre_enable = chv_hdmi_pre_enable; intel_encoder->enable = vlv_enable_hdmi; intel_encoder->post_disable = chv_hdmi_post_disable; + intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable; } else if (IS_VALLEYVIEW(dev)) { intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; intel_encoder->pre_enable = vlv_hdmi_pre_enable; |