drm/i915: implement Haswell DP link train sequence
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_dp.c
index ace757af913366db3e7cff4e670fa9c804c84d08..f6d86492ba3eda4693ee39d79c8d06b1db50bc6b 100644 (file)
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
-#include "drm_dp_helper.h"
 
 #define DP_RECEIVER_CAP_SIZE   0xf
 #define DP_LINK_STATUS_SIZE    6
 #define DP_LINK_CHECK_TIMEOUT  (10 * 1000)
 
-#define DP_LINK_CONFIGURATION_SIZE     9
-
-struct intel_dp {
-       struct intel_encoder base;
-       uint32_t output_reg;
-       uint32_t DP;
-       uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
-       bool has_audio;
-       enum hdmi_force_audio force_audio;
-       uint32_t color_range;
-       int dpms_mode;
-       uint8_t link_bw;
-       uint8_t lane_count;
-       uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
-       struct i2c_adapter adapter;
-       struct i2c_algo_dp_aux_data algo;
-       bool is_pch_edp;
-       uint8_t train_set[4];
-       int panel_power_up_delay;
-       int panel_power_down_delay;
-       int panel_power_cycle_delay;
-       int backlight_on_delay;
-       int backlight_off_delay;
-       struct drm_display_mode *panel_fixed_mode;  /* for eDP */
-       struct delayed_work panel_vdd_work;
-       bool want_panel_vdd;
-       struct edid *edid; /* cached EDID for eDP */
-       int edid_mode_count;
-};
-
 /**
  * is_edp - is the given port attached to an eDP panel (either CPU or PCH)
  * @intel_dp: DP struct
@@ -108,11 +77,6 @@ static bool is_cpu_edp(struct intel_dp *intel_dp)
        return is_edp(intel_dp) && !is_pch_edp(intel_dp);
 }
 
-static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
-{
-       return container_of(encoder, struct intel_dp, base.base);
-}
-
 static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 {
        return container_of(intel_attached_encoder(connector),
@@ -138,8 +102,6 @@ bool intel_encoder_is_pch_edp(struct drm_encoder *encoder)
        return is_pch_edp(intel_dp);
 }
 
-static void intel_dp_start_link_train(struct intel_dp *intel_dp);
-static void intel_dp_complete_link_train(struct intel_dp *intel_dp);
 static void intel_dp_link_down(struct intel_dp *intel_dp);
 
 void
@@ -317,6 +279,10 @@ intel_hrawclk(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t clkcfg;
 
+       /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
+       if (IS_VALLEYVIEW(dev))
+               return 200;
+
        clkcfg = I915_READ(CLKCFG);
        switch (clkcfg & CLKCFG_FSB_MASK) {
        case CLKCFG_FSB_400:
@@ -388,6 +354,29 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        uint32_t aux_clock_divider;
        int try, precharge;
 
+       if (IS_HASWELL(dev)) {
+               switch (intel_dp->port) {
+               case PORT_A:
+                       ch_ctl = DPA_AUX_CH_CTL;
+                       ch_data = DPA_AUX_CH_DATA1;
+                       break;
+               case PORT_B:
+                       ch_ctl = PCH_DPB_AUX_CH_CTL;
+                       ch_data = PCH_DPB_AUX_CH_DATA1;
+                       break;
+               case PORT_C:
+                       ch_ctl = PCH_DPC_AUX_CH_CTL;
+                       ch_data = PCH_DPC_AUX_CH_DATA1;
+                       break;
+               case PORT_D:
+                       ch_ctl = PCH_DPD_AUX_CH_CTL;
+                       ch_data = PCH_DPD_AUX_CH_DATA1;
+                       break;
+               default:
+                       BUG();
+               }
+       }
+
        intel_dp_check_edp(intel_dp);
        /* The clock divider is based off the hrawclk,
         * and would like to run at 2MHz. So, take the
@@ -397,7 +386,9 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
         * clock divider.
         */
        if (is_cpu_edp(intel_dp)) {
-               if (IS_GEN6(dev) || IS_GEN7(dev))
+               if (IS_VALLEYVIEW(dev))
+                       aux_clock_divider = 100;
+               else if (IS_GEN6(dev) || IS_GEN7(dev))
                        aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
                else
                        aux_clock_divider = 225; /* eDP input clock at 450Mhz */
@@ -823,25 +814,44 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
        intel_dp_compute_m_n(intel_crtc->bpp, lane_count,
                             mode->clock, adjusted_mode->clock, &m_n);
 
-       if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(TRANSDATA_M1(pipe),
-                          ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-                          m_n.gmch_m);
+       if (IS_HASWELL(dev)) {
+               I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
+               I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
+               I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
+               I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
+       } else if (HAS_PCH_SPLIT(dev)) {
+               I915_WRITE(TRANSDATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
                I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n);
                I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m);
                I915_WRITE(TRANSDPLINK_N1(pipe), m_n.link_n);
+       } else if (IS_VALLEYVIEW(dev)) {
+               I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
+               I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
+               I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
+               I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
        } else {
                I915_WRITE(PIPE_GMCH_DATA_M(pipe),
-                          ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-                          m_n.gmch_m);
+                          TU_SIZE(m_n.tu) | m_n.gmch_m);
                I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n);
                I915_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m);
                I915_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n);
        }
 }
 
-static void ironlake_edp_pll_on(struct drm_encoder *encoder);
-static void ironlake_edp_pll_off(struct drm_encoder *encoder);
+void intel_dp_init_link_config(struct intel_dp *intel_dp)
+{
+       memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+       intel_dp->link_configuration[0] = intel_dp->link_bw;
+       intel_dp->link_configuration[1] = intel_dp->lane_count;
+       intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
+       /*
+        * Check for DPCD version > 1.1 and enhanced framing support
+        */
+       if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
+           (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
+               intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+       }
+}
 
 static void
 intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
@@ -853,14 +863,6 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        struct drm_crtc *crtc = intel_dp->base.base.crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       /* Turn on the eDP PLL if needed */
-       if (is_edp(intel_dp)) {
-               if (!is_pch_edp(intel_dp))
-                       ironlake_edp_pll_on(encoder);
-               else
-                       ironlake_edp_pll_off(encoder);
-       }
-
        /*
         * There are four kinds of DP registers:
         *
@@ -882,10 +884,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
         * supposed to be read-only.
         */
        intel_dp->DP = I915_READ(intel_dp->output_reg) & DP_DETECTED;
-       intel_dp->DP |=  DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
        /* Handle DP bits in common between all three register formats */
-
        intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
        switch (intel_dp->lane_count) {
@@ -905,21 +905,12 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
                intel_write_eld(encoder, adjusted_mode);
        }
-       memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
-       intel_dp->link_configuration[0] = intel_dp->link_bw;
-       intel_dp->link_configuration[1] = intel_dp->lane_count;
-       intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
-       /*
-        * Check for DPCD version > 1.1 and enhanced framing support
-        */
-       if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
-           (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
-               intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-       }
+
+       intel_dp_init_link_config(intel_dp);
 
        /* Split out the IBX/CPU vs CPT settings */
 
-       if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+       if (is_cpu_edp(intel_dp) && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) {
                if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
                        intel_dp->DP |= DP_SYNC_HS_HIGH;
                if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -932,7 +923,6 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                intel_dp->DP |= intel_crtc->pipe << 29;
 
                /* don't miss out required setting for eDP */
-               intel_dp->DP |= DP_PLL_ENABLE;
                if (adjusted_mode->clock < 200000)
                        intel_dp->DP |= DP_PLL_FREQ_160MHZ;
                else
@@ -954,7 +944,6 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 
                if (is_cpu_edp(intel_dp)) {
                        /* don't miss out required setting for eDP */
-                       intel_dp->DP |= DP_PLL_ENABLE;
                        if (adjusted_mode->clock < 200000)
                                intel_dp->DP |= DP_PLL_FREQ_160MHZ;
                        else
@@ -1225,27 +1214,49 @@ static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
        msleep(intel_dp->backlight_off_delay);
 }
 
-static void ironlake_edp_pll_on(struct drm_encoder *encoder)
+static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = encoder->dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
+       struct drm_crtc *crtc = intel_dp->base.base.crtc;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 dpa_ctl;
 
+       assert_pipe_disabled(dev_priv,
+                            to_intel_crtc(crtc)->pipe);
+
        DRM_DEBUG_KMS("\n");
        dpa_ctl = I915_READ(DP_A);
-       dpa_ctl |= DP_PLL_ENABLE;
-       I915_WRITE(DP_A, dpa_ctl);
+       WARN(dpa_ctl & DP_PLL_ENABLE, "dp pll on, should be off\n");
+       WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n");
+
+       /* We don't adjust intel_dp->DP while tearing down the link, to
+        * facilitate link retraining (e.g. after hotplug). Hence clear all
+        * enable bits here to ensure that we don't enable too much. */
+       intel_dp->DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE);
+       intel_dp->DP |= DP_PLL_ENABLE;
+       I915_WRITE(DP_A, intel_dp->DP);
        POSTING_READ(DP_A);
        udelay(200);
 }
 
-static void ironlake_edp_pll_off(struct drm_encoder *encoder)
+static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = encoder->dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
+       struct drm_crtc *crtc = intel_dp->base.base.crtc;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 dpa_ctl;
 
+       assert_pipe_disabled(dev_priv,
+                            to_intel_crtc(crtc)->pipe);
+
        dpa_ctl = I915_READ(DP_A);
+       WARN((dpa_ctl & DP_PLL_ENABLE) == 0,
+            "dp pll off, should be on\n");
+       WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n");
+
+       /* We can't rely on the value tracked for the DP register in
+        * intel_dp->DP because link_down must not change that (otherwise link
+        * re-training will fail. */
        dpa_ctl &= ~DP_PLL_ENABLE;
        I915_WRITE(DP_A, dpa_ctl);
        POSTING_READ(DP_A);
@@ -1253,7 +1264,7 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder)
 }
 
 /* If the sink supports it, try to set the power state appropriately */
-static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
+void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 {
        int ret, i;
 
@@ -1282,10 +1293,57 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
        }
 }
 
-static void intel_dp_prepare(struct drm_encoder *encoder)
+static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
+                                 enum pipe *pipe)
 {
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp = I915_READ(intel_dp->output_reg);
+
+       if (!(tmp & DP_PORT_EN))
+               return false;
+
+       if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+               *pipe = PORT_TO_PIPE_CPT(tmp);
+       } else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
+               *pipe = PORT_TO_PIPE(tmp);
+       } else {
+               u32 trans_sel;
+               u32 trans_dp;
+               int i;
+
+               switch (intel_dp->output_reg) {
+               case PCH_DP_B:
+                       trans_sel = TRANS_DP_PORT_SEL_B;
+                       break;
+               case PCH_DP_C:
+                       trans_sel = TRANS_DP_PORT_SEL_C;
+                       break;
+               case PCH_DP_D:
+                       trans_sel = TRANS_DP_PORT_SEL_D;
+                       break;
+               default:
+                       return true;
+               }
+
+               for_each_pipe(i) {
+                       trans_dp = I915_READ(TRANS_DP_CTL(i));
+                       if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) {
+                               *pipe = i;
+                               return true;
+                       }
+               }
+       }
 
+       DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", intel_dp->output_reg);
+
+       return true;
+}
+
+static void intel_disable_dp(struct intel_encoder *encoder)
+{
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
        /* Make sure the panel is off before trying to change the mode. But also
         * ensure that we have vdd while we switch off the panel. */
@@ -1293,14 +1351,31 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
        ironlake_edp_backlight_off(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
        ironlake_edp_panel_off(intel_dp);
-       intel_dp_link_down(intel_dp);
+
+       /* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */
+       if (!is_cpu_edp(intel_dp))
+               intel_dp_link_down(intel_dp);
 }
 
-static void intel_dp_commit(struct drm_encoder *encoder)
+static void intel_post_disable_dp(struct intel_encoder *encoder)
 {
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       struct drm_device *dev = encoder->dev;
-       struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+       if (is_cpu_edp(intel_dp)) {
+               intel_dp_link_down(intel_dp);
+               ironlake_edp_pll_off(intel_dp);
+       }
+}
+
+static void intel_enable_dp(struct intel_encoder *encoder)
+{
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dp_reg = I915_READ(intel_dp->output_reg);
+
+       if (WARN_ON(dp_reg & DP_PORT_EN))
+               return;
 
        ironlake_edp_panel_vdd_on(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
@@ -1309,47 +1384,14 @@ static void intel_dp_commit(struct drm_encoder *encoder)
        ironlake_edp_panel_vdd_off(intel_dp, true);
        intel_dp_complete_link_train(intel_dp);
        ironlake_edp_backlight_on(intel_dp);
-
-       intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
-
-       if (HAS_PCH_CPT(dev))
-               intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
-static void
-intel_dp_dpms(struct drm_encoder *encoder, int mode)
+static void intel_pre_enable_dp(struct intel_encoder *encoder)
 {
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t dp_reg = I915_READ(intel_dp->output_reg);
-
-       if (mode != DRM_MODE_DPMS_ON) {
-               /* Switching the panel off requires vdd. */
-               ironlake_edp_panel_vdd_on(intel_dp);
-               ironlake_edp_backlight_off(intel_dp);
-               intel_dp_sink_dpms(intel_dp, mode);
-               ironlake_edp_panel_off(intel_dp);
-               intel_dp_link_down(intel_dp);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
-               if (is_cpu_edp(intel_dp))
-                       ironlake_edp_pll_off(encoder);
-       } else {
-               if (is_cpu_edp(intel_dp))
-                       ironlake_edp_pll_on(encoder);
-
-               ironlake_edp_panel_vdd_on(intel_dp);
-               intel_dp_sink_dpms(intel_dp, mode);
-               if (!(dp_reg & DP_PORT_EN)) {
-                       intel_dp_start_link_train(intel_dp);
-                       ironlake_edp_panel_on(intel_dp);
-                       ironlake_edp_panel_vdd_off(intel_dp, true);
-                       intel_dp_complete_link_train(intel_dp);
-               } else
-                       ironlake_edp_panel_vdd_off(intel_dp, false);
-               ironlake_edp_backlight_on(intel_dp);
-       }
-       intel_dp->dpms_mode = mode;
+       if (is_cpu_edp(intel_dp))
+               ironlake_edp_pll_on(intel_dp);
 }
 
 /*
@@ -1457,7 +1499,19 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
 {
        struct drm_device *dev = intel_dp->base.base.dev;
 
-       if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+       if (IS_HASWELL(dev)) {
+               switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+               case DP_TRAIN_VOLTAGE_SWING_400:
+                       return DP_TRAIN_PRE_EMPHASIS_9_5;
+               case DP_TRAIN_VOLTAGE_SWING_600:
+                       return DP_TRAIN_PRE_EMPHASIS_6;
+               case DP_TRAIN_VOLTAGE_SWING_800:
+                       return DP_TRAIN_PRE_EMPHASIS_3_5;
+               case DP_TRAIN_VOLTAGE_SWING_1200:
+               default:
+                       return DP_TRAIN_PRE_EMPHASIS_0;
+               }
+       } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
                switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
                case DP_TRAIN_VOLTAGE_SWING_400:
                        return DP_TRAIN_PRE_EMPHASIS_6;
@@ -1611,6 +1665,40 @@ intel_gen7_edp_signal_levels(uint8_t train_set)
        }
 }
 
+/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */
+static uint32_t
+intel_dp_signal_levels_hsw(uint8_t train_set)
+{
+       int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
+                                        DP_TRAIN_PRE_EMPHASIS_MASK);
+       switch (signal_levels) {
+       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
+               return DDI_BUF_EMP_400MV_0DB_HSW;
+       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
+               return DDI_BUF_EMP_400MV_3_5DB_HSW;
+       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
+               return DDI_BUF_EMP_400MV_6DB_HSW;
+       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_9_5:
+               return DDI_BUF_EMP_400MV_9_5DB_HSW;
+
+       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
+               return DDI_BUF_EMP_600MV_0DB_HSW;
+       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
+               return DDI_BUF_EMP_600MV_3_5DB_HSW;
+       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
+               return DDI_BUF_EMP_600MV_6DB_HSW;
+
+       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
+               return DDI_BUF_EMP_800MV_0DB_HSW;
+       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
+               return DDI_BUF_EMP_800MV_3_5DB_HSW;
+       default:
+               DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
+                             "0x%x\n", signal_levels);
+               return DDI_BUF_EMP_400MV_0DB_HSW;
+       }
+}
+
 static uint8_t
 intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
                      int lane)
@@ -1667,6 +1755,81 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
        struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
+       uint32_t temp;
+
+       if (IS_HASWELL(dev)) {
+               temp = I915_READ(DP_TP_CTL(intel_dp->port));
+
+               if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
+                       temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
+               else
+                       temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
+
+               temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+               case DP_TRAINING_PATTERN_DISABLE:
+                       temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
+                       I915_WRITE(DP_TP_CTL(intel_dp->port), temp);
+
+                       if (wait_for((I915_READ(DP_TP_STATUS(intel_dp->port)) &
+                                     DP_TP_STATUS_IDLE_DONE), 1))
+                               DRM_ERROR("Timed out waiting for DP idle patterns\n");
+
+                       temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+                       temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
+
+                       break;
+               case DP_TRAINING_PATTERN_1:
+                       temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
+                       break;
+               case DP_TRAINING_PATTERN_2:
+                       temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
+                       break;
+               case DP_TRAINING_PATTERN_3:
+                       temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
+                       break;
+               }
+               I915_WRITE(DP_TP_CTL(intel_dp->port), temp);
+
+       } else if (HAS_PCH_CPT(dev) &&
+                  (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
+               dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT;
+
+               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+               case DP_TRAINING_PATTERN_DISABLE:
+                       dp_reg_value |= DP_LINK_TRAIN_OFF_CPT;
+                       break;
+               case DP_TRAINING_PATTERN_1:
+                       dp_reg_value |= DP_LINK_TRAIN_PAT_1_CPT;
+                       break;
+               case DP_TRAINING_PATTERN_2:
+                       dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT;
+                       break;
+               case DP_TRAINING_PATTERN_3:
+                       DRM_ERROR("DP training pattern 3 not supported\n");
+                       dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT;
+                       break;
+               }
+
+       } else {
+               dp_reg_value &= ~DP_LINK_TRAIN_MASK;
+
+               switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+               case DP_TRAINING_PATTERN_DISABLE:
+                       dp_reg_value |= DP_LINK_TRAIN_OFF;
+                       break;
+               case DP_TRAINING_PATTERN_1:
+                       dp_reg_value |= DP_LINK_TRAIN_PAT_1;
+                       break;
+               case DP_TRAINING_PATTERN_2:
+                       dp_reg_value |= DP_LINK_TRAIN_PAT_2;
+                       break;
+               case DP_TRAINING_PATTERN_3:
+                       DRM_ERROR("DP training pattern 3 not supported\n");
+                       dp_reg_value |= DP_LINK_TRAIN_PAT_2;
+                       break;
+               }
+       }
 
        I915_WRITE(intel_dp->output_reg, dp_reg_value);
        POSTING_READ(intel_dp->output_reg);
@@ -1675,40 +1838,33 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
                                    DP_TRAINING_PATTERN_SET,
                                    dp_train_pat);
 
-       ret = intel_dp_aux_native_write(intel_dp,
-                                       DP_TRAINING_LANE0_SET,
-                                       intel_dp->train_set,
-                                       intel_dp->lane_count);
-       if (ret != intel_dp->lane_count)
-               return false;
+       if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) !=
+           DP_TRAINING_PATTERN_DISABLE) {
+               ret = intel_dp_aux_native_write(intel_dp,
+                                               DP_TRAINING_LANE0_SET,
+                                               intel_dp->train_set,
+                                               intel_dp->lane_count);
+               if (ret != intel_dp->lane_count)
+                       return false;
+       }
 
        return true;
 }
 
 /* Enable corresponding port and start training pattern 1 */
-static void
+void
 intel_dp_start_link_train(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = intel_dp->base.base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+       struct drm_encoder *encoder = &intel_dp->base.base;
+       struct drm_device *dev = encoder->dev;
        int i;
        uint8_t voltage;
        bool clock_recovery = false;
        int voltage_tries, loop_tries;
-       u32 reg;
        uint32_t DP = intel_dp->DP;
 
-       /*
-        * On CPT we have to enable the port in training pattern 1, which
-        * will happen below in intel_dp_set_link_train.  Otherwise, enable
-        * the port and wait for it to become active.
-        */
-       if (!HAS_PCH_CPT(dev)) {
-               I915_WRITE(intel_dp->output_reg, intel_dp->DP);
-               POSTING_READ(intel_dp->output_reg);
-               intel_wait_for_vblank(dev, intel_crtc->pipe);
-       }
+       if (IS_HASWELL(dev))
+               intel_ddi_prepare_link_retrain(encoder);
 
        /* Write the link configuration data */
        intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
@@ -1717,10 +1873,6 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 
        DP |= DP_PORT_EN;
 
-       if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-               DP &= ~DP_LINK_TRAIN_MASK_CPT;
-       else
-               DP &= ~DP_LINK_TRAIN_MASK;
        memset(intel_dp->train_set, 0, 4);
        voltage = 0xff;
        voltage_tries = 0;
@@ -1731,8 +1883,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                uint8_t     link_status[DP_LINK_STATUS_SIZE];
                uint32_t    signal_levels;
 
-
-               if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+               if (IS_HASWELL(dev)) {
+                       signal_levels = intel_dp_signal_levels_hsw(
+                                                       intel_dp->train_set[0]);
+                       DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels;
+               } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
                        signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
                } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
@@ -1740,16 +1895,12 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
                        signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
-                       DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
+               DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n",
+                             signal_levels);
 
-               if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-                       reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
-               else
-                       reg = DP | DP_LINK_TRAIN_PAT_1;
-
-               if (!intel_dp_set_link_train(intel_dp, reg,
+               if (!intel_dp_set_link_train(intel_dp, DP,
                                             DP_TRAINING_PATTERN_1 |
                                             DP_LINK_SCRAMBLING_DISABLE))
                        break;
@@ -1800,14 +1951,12 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
        intel_dp->DP = DP;
 }
 
-static void
+void
 intel_dp_complete_link_train(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp->base.base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        bool channel_eq = false;
        int tries, cr_tries;
-       u32 reg;
        uint32_t DP = intel_dp->DP;
 
        /* channel equalization */
@@ -1825,7 +1974,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                        break;
                }
 
-               if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+               if (IS_HASWELL(dev)) {
+                       signal_levels = intel_dp_signal_levels_hsw(intel_dp->train_set[0]);
+                       DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels;
+               } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
                        signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
                } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
@@ -1836,13 +1988,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
-               if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-                       reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
-               else
-                       reg = DP | DP_LINK_TRAIN_PAT_2;
-
                /* channel eq pattern */
-               if (!intel_dp_set_link_train(intel_dp, reg,
+               if (!intel_dp_set_link_train(intel_dp, DP,
                                             DP_TRAINING_PATTERN_2 |
                                             DP_LINK_SCRAMBLING_DISABLE))
                        break;
@@ -1877,15 +2024,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                ++tries;
        }
 
-       if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-               reg = DP | DP_LINK_TRAIN_OFF_CPT;
-       else
-               reg = DP | DP_LINK_TRAIN_OFF;
+       if (channel_eq)
+               DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n");
 
-       I915_WRITE(intel_dp->output_reg, reg);
-       POSTING_READ(intel_dp->output_reg);
-       intel_dp_aux_native_write_1(intel_dp,
-                                   DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
+       intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
 }
 
 static void
@@ -1895,17 +2037,28 @@ intel_dp_link_down(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t DP = intel_dp->DP;
 
-       if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
+       /*
+        * DDI code has a strict mode set sequence and we should try to respect
+        * it, otherwise we might hang the machine in many different ways. So we
+        * really should be disabling the port only on a complete crtc_disable
+        * sequence. This function is just called under two conditions on DDI
+        * code:
+        * - Link train failed while doing crtc_enable, and on this case we
+        *   really should respect the mode set sequence and wait for a
+        *   crtc_disable.
+        * - Someone turned the monitor off and intel_dp_check_link_status
+        *   called us. We don't need to disable the whole port on this case, so
+        *   when someone turns the monitor on again,
+        *   intel_ddi_prepare_link_retrain will take care of redoing the link
+        *   train.
+        */
+       if (IS_HASWELL(dev))
                return;
 
-       DRM_DEBUG_KMS("\n");
+       if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0))
+               return;
 
-       if (is_edp(intel_dp)) {
-               DP &= ~DP_PLL_ENABLE;
-               I915_WRITE(intel_dp->output_reg, DP);
-               POSTING_READ(intel_dp->output_reg);
-               udelay(100);
-       }
+       DRM_DEBUG_KMS("\n");
 
        if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
                DP &= ~DP_LINK_TRAIN_MASK_CPT;
@@ -1918,13 +2071,6 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
        msleep(17);
 
-       if (is_edp(intel_dp)) {
-               if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-                       DP |= DP_LINK_TRAIN_OFF_CPT;
-               else
-                       DP |= DP_LINK_TRAIN_OFF;
-       }
-
        if (HAS_PCH_IBX(dev) &&
            I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
                struct drm_crtc *crtc = intel_dp->base.base.crtc;
@@ -1968,12 +2114,25 @@ static bool
 intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
        if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
-                                          sizeof(intel_dp->dpcd)) &&
-           (intel_dp->dpcd[DP_DPCD_REV] != 0)) {
-               return true;
-       }
+                                          sizeof(intel_dp->dpcd)) == 0)
+               return false; /* aux transfer failed */
 
-       return false;
+       if (intel_dp->dpcd[DP_DPCD_REV] == 0)
+               return false; /* DPCD not present */
+
+       if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
+             DP_DWN_STRM_PORT_PRESENT))
+               return true; /* native DP sink */
+
+       if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
+               return true; /* no per-port downstream info */
+
+       if (intel_dp_aux_native_read_retry(intel_dp, DP_DOWNSTREAM_PORT_0,
+                                          intel_dp->downstream_ports,
+                                          DP_MAX_DOWNSTREAM_PORTS) == 0)
+               return false; /* downstream port status fetch failed */
+
+       return true;
 }
 
 static void
@@ -2033,10 +2192,10 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
        u8 sink_irq_vector;
        u8 link_status[DP_LINK_STATUS_SIZE];
 
-       if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
+       if (!intel_dp->base.connectors_active)
                return;
 
-       if (!intel_dp->base.base.crtc)
+       if (WARN_ON(!intel_dp->base.base.crtc))
                return;
 
        /* Try to read receiver status if the link appears to be up */
@@ -2073,11 +2232,43 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
        }
 }
 
+/* XXX this is probably wrong for multiple downstream ports */
 static enum drm_connector_status
 intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 {
-       if (intel_dp_get_dpcd(intel_dp))
+       uint8_t *dpcd = intel_dp->dpcd;
+       bool hpd;
+       uint8_t type;
+
+       if (!intel_dp_get_dpcd(intel_dp))
+               return connector_status_disconnected;
+
+       /* if there's no downstream port, we're done */
+       if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
+               return connector_status_connected;
+
+       /* If we're HPD-aware, SINK_COUNT changes dynamically */
+       hpd = !!(intel_dp->downstream_ports[0] & DP_DS_PORT_HPD);
+       if (hpd) {
+               uint8_t reg;
+               if (!intel_dp_aux_native_read_retry(intel_dp, DP_SINK_COUNT,
+                                                   &reg, 1))
+                       return connector_status_unknown;
+               return DP_GET_SINK_COUNT(reg) ? connector_status_connected
+                                             : connector_status_disconnected;
+       }
+
+       /* If no HPD, poke DDC gently */
+       if (drm_probe_ddc(&intel_dp->adapter))
                return connector_status_connected;
+
+       /* Well we tried, say unknown for unreliable port types */
+       type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
+       if (type == DP_DS_PORT_TYPE_VGA || type == DP_DS_PORT_TYPE_NON_EDID)
+               return connector_status_unknown;
+
+       /* Anything else is out of spec, warn and ignore */
+       DRM_DEBUG_KMS("Broken DP branch device, ignoring\n");
        return connector_status_disconnected;
 }
 
@@ -2160,7 +2351,6 @@ intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *ada
                ret = drm_add_edid_modes(connector, intel_dp->edid);
                drm_edid_to_eld(connector,
                                intel_dp->edid);
-               connector->display_info.raw_edid = NULL;
                return intel_dp->edid_mode_count;
        }
 
@@ -2206,7 +2396,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                edid = intel_dp_get_edid(connector, &intel_dp->adapter);
                if (edid) {
                        intel_dp->has_audio = drm_detect_monitor_audio(edid);
-                       connector->display_info.raw_edid = NULL;
                        kfree(edid);
                }
        }
@@ -2271,8 +2460,6 @@ intel_dp_detect_audio(struct drm_connector *connector)
        edid = intel_dp_get_edid(connector, &intel_dp->adapter);
        if (edid) {
                has_audio = drm_detect_monitor_audio(edid);
-
-               connector->display_info.raw_edid = NULL;
                kfree(edid);
        }
 
@@ -2326,9 +2513,8 @@ intel_dp_set_property(struct drm_connector *connector,
 done:
        if (intel_dp->base.base.crtc) {
                struct drm_crtc *crtc = intel_dp->base.base.crtc;
-               drm_crtc_helper_set_mode(crtc, &crtc->mode,
-                                        crtc->x, crtc->y,
-                                        crtc->fb);
+               intel_set_mode(crtc, &crtc->mode,
+                              crtc->x, crtc->y, crtc->fb);
        }
 
        return 0;
@@ -2362,15 +2548,13 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 }
 
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
-       .dpms = intel_dp_dpms,
        .mode_fixup = intel_dp_mode_fixup,
-       .prepare = intel_dp_prepare,
        .mode_set = intel_dp_mode_set,
-       .commit = intel_dp_commit,
+       .disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
+       .dpms = intel_connector_dpms,
        .detect = intel_dp_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = intel_dp_set_property,
@@ -2441,7 +2625,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 }
 
 void
-intel_dp_init(struct drm_device *dev, int output_reg)
+intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_connector *connector;
@@ -2456,7 +2640,9 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                return;
 
        intel_dp->output_reg = output_reg;
-       intel_dp->dpms_mode = -1;
+       intel_dp->port = port;
+       /* Preserve the current hw state. */
+       intel_dp->DP = I915_READ(intel_dp->output_reg);
 
        intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
        if (!intel_connector) {
@@ -2469,7 +2655,14 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                if (intel_dpd_is_edp(dev))
                        intel_dp->is_pch_edp = true;
 
-       if (output_reg == DP_A || is_pch_edp(intel_dp)) {
+       /*
+        * FIXME : We need to initialize built-in panels before external panels.
+        * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
+        */
+       if (IS_VALLEYVIEW(dev) && output_reg == DP_C) {
+               type = DRM_MODE_CONNECTOR_eDP;
+               intel_encoder->type = INTEL_OUTPUT_EDP;
+       } else if (output_reg == DP_A || is_pch_edp(intel_dp)) {
                type = DRM_MODE_CONNECTOR_eDP;
                intel_encoder->type = INTEL_OUTPUT_EDP;
        } else {
@@ -2483,18 +2676,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
        connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-       if (output_reg == DP_B || output_reg == PCH_DP_B)
-               intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
-       else if (output_reg == DP_C || output_reg == PCH_DP_C)
-               intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
-       else if (output_reg == DP_D || output_reg == PCH_DP_D)
-               intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+       intel_encoder->cloneable = false;
 
-       if (is_edp(intel_dp)) {
-               intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
-               INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
-                                 ironlake_panel_vdd_work);
-       }
+       INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+                         ironlake_panel_vdd_work);
 
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
@@ -2508,29 +2693,33 @@ intel_dp_init(struct drm_device *dev, int output_reg)
        intel_connector_attach_encoder(intel_connector, intel_encoder);
        drm_sysfs_connector_add(connector);
 
+       intel_encoder->enable = intel_enable_dp;
+       intel_encoder->pre_enable = intel_pre_enable_dp;
+       intel_encoder->disable = intel_disable_dp;
+       intel_encoder->post_disable = intel_post_disable_dp;
+       intel_encoder->get_hw_state = intel_dp_get_hw_state;
+       intel_connector->get_hw_state = intel_connector_get_hw_state;
+
        /* Set up the DDC bus. */
-       switch (output_reg) {
-               case DP_A:
-                       name = "DPDDC-A";
-                       break;
-               case DP_B:
-               case PCH_DP_B:
-                       dev_priv->hotplug_supported_mask |=
-                               DPB_HOTPLUG_INT_STATUS;
-                       name = "DPDDC-B";
-                       break;
-               case DP_C:
-               case PCH_DP_C:
-                       dev_priv->hotplug_supported_mask |=
-                               DPC_HOTPLUG_INT_STATUS;
-                       name = "DPDDC-C";
-                       break;
-               case DP_D:
-               case PCH_DP_D:
-                       dev_priv->hotplug_supported_mask |=
-                               DPD_HOTPLUG_INT_STATUS;
-                       name = "DPDDC-D";
-                       break;
+       switch (port) {
+       case PORT_A:
+               name = "DPDDC-A";
+               break;
+       case PORT_B:
+               dev_priv->hotplug_supported_mask |= DPB_HOTPLUG_INT_STATUS;
+               name = "DPDDC-B";
+               break;
+       case PORT_C:
+               dev_priv->hotplug_supported_mask |= DPC_HOTPLUG_INT_STATUS;
+               name = "DPDDC-C";
+               break;
+       case PORT_D:
+               dev_priv->hotplug_supported_mask |= DPD_HOTPLUG_INT_STATUS;
+               name = "DPDDC-D";
+               break;
+       default:
+               WARN(1, "Invalid port %c\n", port_name(port));
+               break;
        }
 
        /* Cache some DPCD data in the eDP case */
This page took 0.053573 seconds and 5 git commands to generate.