drm/i915: Fix LVDS fixed-mode regression from 219adae1
[pandora-kernel.git] / drivers / gpu / drm / i915 / intel_dp.c
index 9ab8708..c8e0055 100644 (file)
 
 #define DP_LINK_CONFIGURATION_SIZE     9
 
-#define IS_eDP(i) ((i)->base.type == INTEL_OUTPUT_EDP)
-#define IS_PCH_eDP(i) ((i)->is_pch_edp)
-
 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;
+       int force_audio;
        int dpms_mode;
        uint8_t link_bw;
        uint8_t lane_count;
@@ -58,14 +56,69 @@ struct intel_dp {
        struct i2c_adapter adapter;
        struct i2c_algo_dp_aux_data algo;
        bool is_pch_edp;
+       uint8_t train_set[4];
+       uint8_t link_status[DP_LINK_STATUS_SIZE];
+
+       struct drm_property *force_audio_property;
 };
 
+/**
+ * is_edp - is the given port attached to an eDP panel (either CPU or PCH)
+ * @intel_dp: DP struct
+ *
+ * If a CPU or PCH DP output is attached to an eDP panel, this function
+ * will return true, and false otherwise.
+ */
+static bool is_edp(struct intel_dp *intel_dp)
+{
+       return intel_dp->base.type == INTEL_OUTPUT_EDP;
+}
+
+/**
+ * is_pch_edp - is the port on the PCH and attached to an eDP panel?
+ * @intel_dp: DP struct
+ *
+ * Returns true if the given DP struct corresponds to a PCH DP port attached
+ * to an eDP panel, false otherwise.  Helpful for determining whether we
+ * may need FDI resources for a given DP output or not.
+ */
+static bool is_pch_edp(struct intel_dp *intel_dp)
+{
+       return intel_dp->is_pch_edp;
+}
+
 static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
 {
-       return container_of(enc_to_intel_encoder(encoder), struct intel_dp, base);
+       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),
+                           struct intel_dp, base);
+}
+
+/**
+ * intel_encoder_is_pch_edp - is the given encoder a PCH attached eDP?
+ * @encoder: DRM encoder
+ *
+ * Return true if @encoder corresponds to a PCH attached eDP panel.  Needed
+ * by intel_display.c.
+ */
+bool intel_encoder_is_pch_edp(struct drm_encoder *encoder)
+{
+       struct intel_dp *intel_dp;
+
+       if (!encoder)
+               return false;
+
+       intel_dp = enc_to_intel_dp(encoder);
+
+       return is_pch_edp(intel_dp);
 }
 
-static void intel_dp_link_train(struct intel_dp *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
@@ -129,8 +182,8 @@ intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pi
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
-               return (pixel_clock * dev_priv->edp_bpp) / 8;
+       if (is_edp(intel_dp))
+               return (pixel_clock * dev_priv->edp.bpp + 7) / 8;
        else
                return pixel_clock * 3;
 }
@@ -145,15 +198,13 @@ static int
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
 {
-       struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
        int max_lanes = intel_dp_max_lane_count(intel_dp);
 
-       if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
-           dev_priv->panel_fixed_mode) {
+       if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
                if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay)
                        return MODE_PANEL;
 
@@ -163,7 +214,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
 
        /* only refuse the mode on non eDP since we have seen some wierd eDP panels
           which are outside spec tolerances but somehow work by magic */
-       if (!IS_eDP(intel_dp) &&
+       if (!is_edp(intel_dp) &&
            (intel_dp_link_required(connector->dev, intel_dp, mode->clock)
             > intel_dp_max_data_rate(max_link_clock, max_lanes)))
                return MODE_CLOCK_HIGH;
@@ -233,7 +284,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
                uint8_t *recv, int recv_size)
 {
        uint32_t output_reg = intel_dp->output_reg;
-       struct drm_device *dev = intel_dp->base.enc.dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t ch_ctl = output_reg + 0x10;
        uint32_t ch_data = ch_ctl + 4;
@@ -246,8 +297,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        /* The clock divider is based off the hrawclk,
         * and would like to run at 2MHz. So, take the
         * hrawclk value and divide by 2 and use that
+        *
+        * Note that PCH attached eDP panels should use a 125MHz input
+        * clock divider.
         */
-       if (IS_eDP(intel_dp)) {
+       if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) {
                if (IS_GEN6(dev))
                        aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
                else
@@ -519,8 +573,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
        int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
        static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 
-       if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
-           dev_priv->panel_fixed_mode) {
+       if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) {
                intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode);
                intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
                                        mode, adjusted_mode);
@@ -531,6 +584,17 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                mode->clock = dev_priv->panel_fixed_mode->clock;
        }
 
+       /* Just use VBT values for eDP */
+       if (is_edp(intel_dp)) {
+               intel_dp->lane_count = dev_priv->edp.lanes;
+               intel_dp->link_bw = dev_priv->edp.rate;
+               adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
+               DRM_DEBUG_KMS("eDP link bw %02x lane count %d clock %d\n",
+                             intel_dp->link_bw, intel_dp->lane_count,
+                             adjusted_mode->clock);
+               return true;
+       }
+
        for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
                for (clock = 0; clock <= max_clock; clock++) {
                        int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
@@ -549,19 +613,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                }
        }
 
-       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
-               /* okay we failed just pick the highest */
-               intel_dp->lane_count = max_lane_count;
-               intel_dp->link_bw = bws[max_clock];
-               adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
-               DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
-                             "count %d clock %d\n",
-                             intel_dp->link_bw, intel_dp->lane_count,
-                             adjusted_mode->clock);
-
-               return true;
-       }
-
        return false;
 }
 
@@ -598,25 +649,6 @@ intel_dp_compute_m_n(int bpp,
        intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
 }
 
-bool intel_pch_has_edp(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_encoder *encoder;
-
-       list_for_each_entry(encoder, &mode_config->encoder_list, head) {
-               struct intel_dp *intel_dp;
-
-               if (encoder->crtc != crtc)
-                       continue;
-
-               intel_dp = enc_to_intel_dp(encoder);
-               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
-                       return intel_dp->is_pch_edp;
-       }
-       return false;
-}
-
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                 struct drm_display_mode *adjusted_mode)
@@ -641,8 +673,10 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                intel_dp = enc_to_intel_dp(encoder);
                if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) {
                        lane_count = intel_dp->lane_count;
-                       if (IS_PCH_eDP(intel_dp))
-                               bpp = dev_priv->edp_bpp;
+                       break;
+               } else if (is_edp(intel_dp)) {
+                       lane_count = dev_priv->edp.lanes;
+                       bpp = dev_priv->edp.bpp;
                        break;
                }
        }
@@ -698,7 +732,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 {
        struct drm_device *dev = encoder->dev;
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       struct drm_crtc *crtc = intel_dp->base.enc.crtc;
+       struct drm_crtc *crtc = intel_dp->base.base.crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
        intel_dp->DP = (DP_VOLTAGE_0_4 |
@@ -709,7 +743,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
                intel_dp->DP |= DP_SYNC_VS_HIGH;
 
-       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
+       if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
                intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
        else
                intel_dp->DP |= DP_LINK_TRAIN_OFF;
@@ -744,7 +778,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
                intel_dp->DP |= DP_PIPEB_SELECT;
 
-       if (IS_eDP(intel_dp)) {
+       if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) {
                /* don't miss out required setting for eDP */
                intel_dp->DP |= DP_PLL_ENABLE;
                if (adjusted_mode->clock < 200000)
@@ -754,13 +788,15 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        }
 }
 
-static void ironlake_edp_panel_on (struct drm_device *dev)
+/* Returns true if the panel was already on when called */
+static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
 {
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp;
+       u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE;
 
        if (I915_READ(PCH_PP_STATUS) & PP_ON)
-               return;
+               return true;
 
        pp = I915_READ(PCH_PP_CONTROL);
 
@@ -771,21 +807,30 @@ static void ironlake_edp_panel_on (struct drm_device *dev)
 
        pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
        I915_WRITE(PCH_PP_CONTROL, pp);
+       POSTING_READ(PCH_PP_CONTROL);
 
-       if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000, 10))
+       /* Ouch. We need to wait here for some panels, like Dell e6510
+        * https://bugs.freedesktop.org/show_bug.cgi?id=29278i
+        */
+       msleep(300);
+
+       if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask,
+                    5000))
                DRM_ERROR("panel on wait timed out: 0x%08x\n",
                          I915_READ(PCH_PP_STATUS));
 
-       pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD);
        pp |= PANEL_POWER_RESET; /* restore panel reset bit */
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
+
+       return false;
 }
 
 static void ironlake_edp_panel_off (struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp;
+       u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK |
+               PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK;
 
        pp = I915_READ(PCH_PP_CONTROL);
 
@@ -796,15 +841,20 @@ static void ironlake_edp_panel_off (struct drm_device *dev)
 
        pp &= ~POWER_TARGET_ON;
        I915_WRITE(PCH_PP_CONTROL, pp);
+       POSTING_READ(PCH_PP_CONTROL);
 
-       if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000, 10))
+       if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
                DRM_ERROR("panel off wait timed out: 0x%08x\n",
                          I915_READ(PCH_PP_STATUS));
 
-       /* Make sure VDD is enabled so DP AUX will work */
-       pp |= EDP_FORCE_VDD | PANEL_POWER_RESET; /* restore panel reset bit */
+       pp |= PANEL_POWER_RESET; /* restore panel reset bit */
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
+
+       /* Ouch. We need to wait here for some panels, like Dell e6510
+        * https://bugs.freedesktop.org/show_bug.cgi?id=29278i
+        */
+       msleep(300);
 }
 
 static void ironlake_edp_backlight_on (struct drm_device *dev)
@@ -813,6 +863,13 @@ static void ironlake_edp_backlight_on (struct drm_device *dev)
        u32 pp;
 
        DRM_DEBUG_KMS("\n");
+       /*
+        * If we enable the backlight right away following a panel power
+        * on, we may see slight flicker as the panel syncs with the eDP
+        * link.  So delay a bit to make sure the image is solid before
+        * allowing it to appear.
+        */
+       msleep(300);
        pp = I915_READ(PCH_PP_CONTROL);
        pp |= EDP_BLC_ENABLE;
        I915_WRITE(PCH_PP_CONTROL, pp);
@@ -837,8 +894,10 @@ static void ironlake_edp_pll_on(struct drm_encoder *encoder)
 
        DRM_DEBUG_KMS("\n");
        dpa_ctl = I915_READ(DP_A);
-       dpa_ctl &= ~DP_PLL_ENABLE;
+       dpa_ctl |= DP_PLL_ENABLE;
        I915_WRITE(DP_A, dpa_ctl);
+       POSTING_READ(DP_A);
+       udelay(200);
 }
 
 static void ironlake_edp_pll_off(struct drm_encoder *encoder)
@@ -848,8 +907,9 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder)
        u32 dpa_ctl;
 
        dpa_ctl = I915_READ(DP_A);
-       dpa_ctl |= DP_PLL_ENABLE;
+       dpa_ctl &= ~DP_PLL_ENABLE;
        I915_WRITE(DP_A, dpa_ctl);
+       POSTING_READ(DP_A);
        udelay(200);
 }
 
@@ -857,29 +917,31 @@ static void intel_dp_prepare(struct drm_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 (IS_eDP(intel_dp)) {
+       if (is_edp(intel_dp)) {
                ironlake_edp_backlight_off(dev);
-               ironlake_edp_panel_on(dev);
-               ironlake_edp_pll_on(encoder);
+               ironlake_edp_panel_on(intel_dp);
+               if (!is_pch_edp(intel_dp))
+                       ironlake_edp_pll_on(encoder);
+               else
+                       ironlake_edp_pll_off(encoder);
        }
-       if (dp_reg & DP_PORT_EN)
-               intel_dp_link_down(intel_dp);
+       intel_dp_link_down(intel_dp);
 }
 
 static void intel_dp_commit(struct drm_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 (!(dp_reg & DP_PORT_EN)) {
-               intel_dp_link_train(intel_dp);
-       }
-       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
+       intel_dp_start_link_train(intel_dp);
+
+       if (is_edp(intel_dp))
+               ironlake_edp_panel_on(intel_dp);
+
+       intel_dp_complete_link_train(intel_dp);
+
+       if (is_edp(intel_dp))
                ironlake_edp_backlight_on(dev);
 }
 
@@ -892,22 +954,22 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
        uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
        if (mode != DRM_MODE_DPMS_ON) {
-               if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
+               if (is_edp(intel_dp))
                        ironlake_edp_backlight_off(dev);
+               intel_dp_link_down(intel_dp);
+               if (is_edp(intel_dp))
                        ironlake_edp_panel_off(dev);
-               }
-               if (dp_reg & DP_PORT_EN)
-                       intel_dp_link_down(intel_dp);
-               if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
+               if (is_edp(intel_dp) && !is_pch_edp(intel_dp))
                        ironlake_edp_pll_off(encoder);
        } else {
+               if (is_edp(intel_dp))
+                       ironlake_edp_panel_on(intel_dp);
                if (!(dp_reg & DP_PORT_EN)) {
-                       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
-                               ironlake_edp_panel_on(dev);
-                       intel_dp_link_train(intel_dp);
-                       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
-                               ironlake_edp_backlight_on(dev);
+                       intel_dp_start_link_train(intel_dp);
+                       intel_dp_complete_link_train(intel_dp);
                }
+               if (is_edp(intel_dp))
+                       ironlake_edp_backlight_on(dev);
        }
        intel_dp->dpms_mode = mode;
 }
@@ -917,14 +979,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
  * link status information
  */
 static bool
-intel_dp_get_link_status(struct intel_dp *intel_dp,
-                        uint8_t link_status[DP_LINK_STATUS_SIZE])
+intel_dp_get_link_status(struct intel_dp *intel_dp)
 {
        int ret;
 
        ret = intel_dp_aux_native_read(intel_dp,
                                       DP_LANE0_1_STATUS,
-                                      link_status, DP_LINK_STATUS_SIZE);
+                                      intel_dp->link_status, DP_LINK_STATUS_SIZE);
        if (ret != DP_LINK_STATUS_SIZE)
                return false;
        return true;
@@ -999,18 +1060,15 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
 }
 
 static void
-intel_get_adjust_train(struct intel_dp *intel_dp,
-                      uint8_t link_status[DP_LINK_STATUS_SIZE],
-                      int lane_count,
-                      uint8_t train_set[4])
+intel_get_adjust_train(struct intel_dp *intel_dp)
 {
        uint8_t v = 0;
        uint8_t p = 0;
        int lane;
 
-       for (lane = 0; lane < lane_count; lane++) {
-               uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane);
-               uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane);
+       for (lane = 0; lane < intel_dp->lane_count; lane++) {
+               uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane);
+               uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
 
                if (this_v > v)
                        v = this_v;
@@ -1025,15 +1083,25 @@ intel_get_adjust_train(struct intel_dp *intel_dp,
                p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
 
        for (lane = 0; lane < 4; lane++)
-               train_set[lane] = v | p;
+               intel_dp->train_set[lane] = v | p;
 }
 
 static uint32_t
-intel_dp_signal_levels(uint8_t train_set, int lane_count)
+intel_dp_signal_levels(struct intel_dp *intel_dp)
 {
-       uint32_t        signal_levels = 0;
+       struct drm_device *dev = intel_dp->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t signal_levels = 0;
+       u8 train_set = intel_dp->train_set[0];
+       u32 vswing = train_set & DP_TRAIN_VOLTAGE_SWING_MASK;
+       u32 preemphasis = train_set & DP_TRAIN_PRE_EMPHASIS_MASK;
+
+       if (is_edp(intel_dp)) {
+               vswing = dev_priv->edp.vswing;
+               preemphasis = dev_priv->edp.preemphasis;
+       }
 
-       switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
+       switch (vswing) {
        case DP_TRAIN_VOLTAGE_SWING_400:
        default:
                signal_levels |= DP_VOLTAGE_0_4;
@@ -1048,7 +1116,7 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count)
                signal_levels |= DP_VOLTAGE_1_2;
                break;
        }
-       switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
+       switch (preemphasis) {
        case DP_TRAIN_PRE_EMPHASIS_0:
        default:
                signal_levels |= DP_PRE_EMPHASIS_0;
@@ -1116,178 +1184,213 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count
                         DP_LANE_CHANNEL_EQ_DONE|\
                         DP_LANE_SYMBOL_LOCKED)
 static bool
-intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+intel_channel_eq_ok(struct intel_dp *intel_dp)
 {
        uint8_t lane_align;
        uint8_t lane_status;
        int lane;
 
-       lane_align = intel_dp_link_status(link_status,
+       lane_align = intel_dp_link_status(intel_dp->link_status,
                                          DP_LANE_ALIGN_STATUS_UPDATED);
        if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
                return false;
-       for (lane = 0; lane < lane_count; lane++) {
-               lane_status = intel_get_lane_status(link_status, lane);
+       for (lane = 0; lane < intel_dp->lane_count; lane++) {
+               lane_status = intel_get_lane_status(intel_dp->link_status, lane);
                if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
                        return false;
        }
        return true;
 }
 
+static bool
+intel_dp_aux_handshake_required(struct intel_dp *intel_dp)
+{
+       struct drm_device *dev = intel_dp->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (is_edp(intel_dp) && dev_priv->no_aux_handshake)
+               return false;
+
+       return true;
+}
+
 static bool
 intel_dp_set_link_train(struct intel_dp *intel_dp,
                        uint32_t dp_reg_value,
-                       uint8_t dp_train_pat,
-                       uint8_t train_set[4])
+                       uint8_t dp_train_pat)
 {
-       struct drm_device *dev = intel_dp->base.enc.dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
        I915_WRITE(intel_dp->output_reg, dp_reg_value);
        POSTING_READ(intel_dp->output_reg);
 
+       if (!intel_dp_aux_handshake_required(intel_dp))
+               return true;
+
        intel_dp_aux_native_write_1(intel_dp,
                                    DP_TRAINING_PATTERN_SET,
                                    dp_train_pat);
 
        ret = intel_dp_aux_native_write(intel_dp,
-                                       DP_TRAINING_LANE0_SET, train_set, 4);
+                                       DP_TRAINING_LANE0_SET,
+                                       intel_dp->train_set, 4);
        if (ret != 4)
                return false;
 
        return true;
 }
 
+/* Enable corresponding port and start training pattern 1 */
 static void
-intel_dp_link_train(struct intel_dp *intel_dp)
+intel_dp_start_link_train(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = intel_dp->base.enc.dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint8_t train_set[4];
-       uint8_t link_status[DP_LINK_STATUS_SIZE];
+       struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
        int i;
        uint8_t voltage;
        bool clock_recovery = false;
-       bool channel_eq = false;
        int tries;
        u32 reg;
        uint32_t DP = intel_dp->DP;
-       struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
 
        /* Enable output, wait for it to become active */
        I915_WRITE(intel_dp->output_reg, intel_dp->DP);
        POSTING_READ(intel_dp->output_reg);
        intel_wait_for_vblank(dev, intel_crtc->pipe);
 
-       /* Write the link configuration data */
-       intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
-                                 intel_dp->link_configuration,
-                                 DP_LINK_CONFIGURATION_SIZE);
+       if (intel_dp_aux_handshake_required(intel_dp))
+               /* Write the link configuration data */
+               intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
+                                         intel_dp->link_configuration,
+                                         DP_LINK_CONFIGURATION_SIZE);
 
        DP |= DP_PORT_EN;
-       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
+       if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
                DP &= ~DP_LINK_TRAIN_MASK_CPT;
        else
                DP &= ~DP_LINK_TRAIN_MASK;
-       memset(train_set, 0, 4);
+       memset(intel_dp->train_set, 0, 4);
        voltage = 0xff;
        tries = 0;
        clock_recovery = false;
        for (;;) {
-               /* Use train_set[0] to set the voltage and pre emphasis values */
+               /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
                uint32_t    signal_levels;
-               if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
-                       signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
+               if (IS_GEN6(dev) && is_edp(intel_dp)) {
+                       signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
-                       signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
+                       signal_levels = intel_dp_signal_levels(intel_dp);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
-               if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
+               if (HAS_PCH_CPT(dev) && !is_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,
-                                            DP_TRAINING_PATTERN_1, train_set))
+                                            DP_TRAINING_PATTERN_1))
                        break;
                /* Set training pattern 1 */
 
-               udelay(100);
-               if (!intel_dp_get_link_status(intel_dp, link_status))
+               udelay(500);
+               if (intel_dp_aux_handshake_required(intel_dp)) {
                        break;
+               } else {
+                       if (!intel_dp_get_link_status(intel_dp))
+                               break;
 
-               if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
-                       clock_recovery = true;
-                       break;
-               }
-
-               /* Check to see if we've tried the max voltage */
-               for (i = 0; i < intel_dp->lane_count; i++)
-                       if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+                       if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+                               clock_recovery = true;
                                break;
-               if (i == intel_dp->lane_count)
-                       break;
+                       }
 
-               /* Check to see if we've tried the same voltage 5 times */
-               if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
-                       ++tries;
-                       if (tries == 5)
+                       /* Check to see if we've tried the max voltage */
+                       for (i = 0; i < intel_dp->lane_count; i++)
+                               if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+                                       break;
+                       if (i == intel_dp->lane_count)
                                break;
-               } else
-                       tries = 0;
-               voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
-               /* Compute new train_set as requested by target */
-               intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
+                       /* Check to see if we've tried the same voltage 5 times */
+                       if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+                               ++tries;
+                               if (tries == 5)
+                                       break;
+                       } else
+                               tries = 0;
+                       voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+                       /* Compute new intel_dp->train_set as requested by target */
+                       intel_get_adjust_train(intel_dp);
+               }
        }
 
+       intel_dp->DP = DP;
+}
+
+static 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;
+       u32 reg;
+       uint32_t DP = intel_dp->DP;
+
        /* channel equalization */
        tries = 0;
        channel_eq = false;
        for (;;) {
-               /* Use train_set[0] to set the voltage and pre emphasis values */
+               /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
                uint32_t    signal_levels;
 
-               if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
-                       signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
+               if (IS_GEN6(dev) && is_edp(intel_dp)) {
+                       signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
-                       signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
+                       signal_levels = intel_dp_signal_levels(intel_dp);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
-               if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
+               if (HAS_PCH_CPT(dev) && !is_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,
-                                            DP_TRAINING_PATTERN_2, train_set))
+                                            DP_TRAINING_PATTERN_2))
                        break;
 
-               udelay(400);
-               if (!intel_dp_get_link_status(intel_dp, link_status))
-                       break;
+               udelay(500);
 
-               if (intel_channel_eq_ok(link_status, intel_dp->lane_count)) {
-                       channel_eq = true;
+               if (!intel_dp_aux_handshake_required(intel_dp)) {
                        break;
-               }
+               } else {
+                       if (!intel_dp_get_link_status(intel_dp))
+                               break;
 
-               /* Try 5 times */
-               if (tries > 5)
-                       break;
+                       if (intel_channel_eq_ok(intel_dp)) {
+                               channel_eq = true;
+                               break;
+                       }
 
-               /* Compute new train_set as requested by target */
-               intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
-               ++tries;
-       }
+                       /* Try 5 times */
+                       if (tries > 5)
+                               break;
 
-       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
+                       /* Compute new intel_dp->train_set as requested by target */
+                       intel_get_adjust_train(intel_dp);
+                       ++tries;
+               }
+       }
+       if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
                reg = DP | DP_LINK_TRAIN_OFF_CPT;
        else
                reg = DP | DP_LINK_TRAIN_OFF;
@@ -1301,32 +1404,31 @@ intel_dp_link_train(struct intel_dp *intel_dp)
 static void
 intel_dp_link_down(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = intel_dp->base.enc.dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t DP = intel_dp->DP;
 
        DRM_DEBUG_KMS("\n");
 
-       if (IS_eDP(intel_dp)) {
+       if (is_edp(intel_dp)) {
                DP &= ~DP_PLL_ENABLE;
                I915_WRITE(intel_dp->output_reg, DP);
                POSTING_READ(intel_dp->output_reg);
                udelay(100);
        }
 
-       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) {
+       if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) {
                DP &= ~DP_LINK_TRAIN_MASK_CPT;
                I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
-               POSTING_READ(intel_dp->output_reg);
        } else {
                DP &= ~DP_LINK_TRAIN_MASK;
                I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
-               POSTING_READ(intel_dp->output_reg);
        }
+       POSTING_READ(intel_dp->output_reg);
 
-       udelay(17000);
+       msleep(17);
 
-       if (IS_eDP(intel_dp))
+       if (is_edp(intel_dp))
                DP |= DP_LINK_TRAIN_OFF;
        I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
        POSTING_READ(intel_dp->output_reg);
@@ -1344,32 +1446,34 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 static void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
-       uint8_t link_status[DP_LINK_STATUS_SIZE];
-
-       if (!intel_dp->base.enc.crtc)
+       if (!intel_dp->base.base.crtc)
                return;
 
-       if (!intel_dp_get_link_status(intel_dp, link_status)) {
+       if (!intel_dp_get_link_status(intel_dp)) {
                intel_dp_link_down(intel_dp);
                return;
        }
 
-       if (!intel_channel_eq_ok(link_status, intel_dp->lane_count))
-               intel_dp_link_train(intel_dp);
+       if (!intel_channel_eq_ok(intel_dp)) {
+               intel_dp_start_link_train(intel_dp);
+               intel_dp_complete_link_train(intel_dp);
+       }
 }
 
 static enum drm_connector_status
-ironlake_dp_detect(struct drm_connector *connector)
+ironlake_dp_detect(struct intel_dp *intel_dp)
 {
-       struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        enum drm_connector_status status;
 
+       /* Can't disconnect eDP */
+       if (is_edp(intel_dp))
+               return connector_status_connected;
+
        status = connector_status_disconnected;
        if (intel_dp_aux_native_read(intel_dp,
                                     0x000, intel_dp->dpcd,
-                                    sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
-       {
+                                    sizeof (intel_dp->dpcd))
+           == sizeof(intel_dp->dpcd)) {
                if (intel_dp->dpcd[0] != 0)
                        status = connector_status_connected;
        }
@@ -1378,26 +1482,13 @@ ironlake_dp_detect(struct drm_connector *connector)
        return status;
 }
 
-/**
- * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
- *
- * \return true if DP port is connected.
- * \return false if DP port is disconnected.
- */
 static enum drm_connector_status
-intel_dp_detect(struct drm_connector *connector, bool force)
+g4x_dp_detect(struct intel_dp *intel_dp)
 {
-       struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       struct drm_device *dev = intel_dp->base.enc.dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t temp, bit;
        enum drm_connector_status status;
-
-       intel_dp->has_audio = false;
-
-       if (HAS_PCH_SPLIT(dev))
-               return ironlake_dp_detect(connector);
+       uint32_t temp, bit;
 
        switch (intel_dp->output_reg) {
        case DP_B:
@@ -1419,31 +1510,66 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                return connector_status_disconnected;
 
        status = connector_status_disconnected;
-       if (intel_dp_aux_native_read(intel_dp,
-                                    0x000, intel_dp->dpcd,
+       if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd,
                                     sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
        {
                if (intel_dp->dpcd[0] != 0)
                        status = connector_status_connected;
        }
+
        return status;
 }
 
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
+ *
+ * \return true if DP port is connected.
+ * \return false if DP port is disconnected.
+ */
+static enum drm_connector_status
+intel_dp_detect(struct drm_connector *connector, bool force)
+{
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
+       struct drm_device *dev = intel_dp->base.base.dev;
+       enum drm_connector_status status;
+       struct edid *edid = NULL;
+
+       intel_dp->has_audio = false;
+
+       if (HAS_PCH_SPLIT(dev))
+               status = ironlake_dp_detect(intel_dp);
+       else
+               status = g4x_dp_detect(intel_dp);
+       if (status != connector_status_connected)
+               return status;
+
+       if (intel_dp->force_audio) {
+               intel_dp->has_audio = intel_dp->force_audio > 0;
+       } else {
+               edid = drm_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);
+               }
+       }
+
+       return connector_status_connected;
+}
+
 static int intel_dp_get_modes(struct drm_connector *connector)
 {
-       struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       struct drm_device *dev = intel_dp->base.enc.dev;
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
        /* We should parse the EDID data and find out if it has an audio sink
         */
 
-       ret = intel_ddc_get_modes(connector, intel_dp->base.ddc_bus);
+       ret = intel_ddc_get_modes(connector, &intel_dp->adapter);
        if (ret) {
-               if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
-                   !dev_priv->panel_fixed_mode) {
+               if (is_edp(intel_dp) && !dev_priv->panel_fixed_mode) {
                        struct drm_display_mode *newmode;
                        list_for_each_entry(newmode, &connector->probed_modes,
                                            head) {
@@ -1459,7 +1585,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
        }
 
        /* if eDP has no EDID, try to use fixed panel mode from VBT */
-       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
+       if (is_edp(intel_dp)) {
                if (dev_priv->panel_fixed_mode != NULL) {
                        struct drm_display_mode *mode;
                        mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
@@ -1470,6 +1596,46 @@ static int intel_dp_get_modes(struct drm_connector *connector)
        return 0;
 }
 
+static int
+intel_dp_set_property(struct drm_connector *connector,
+                     struct drm_property *property,
+                     uint64_t val)
+{
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
+       int ret;
+
+       ret = drm_connector_property_set_value(connector, property, val);
+       if (ret)
+               return ret;
+
+       if (property == intel_dp->force_audio_property) {
+               if (val == intel_dp->force_audio)
+                       return 0;
+
+               intel_dp->force_audio = val;
+
+               if (val > 0 && intel_dp->has_audio)
+                       return 0;
+               if (val < 0 && !intel_dp->has_audio)
+                       return 0;
+
+               intel_dp->has_audio = val > 0;
+               goto done;
+       }
+
+       return -EINVAL;
+
+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);
+       }
+
+       return 0;
+}
+
 static void
 intel_dp_destroy (struct drm_connector *connector)
 {
@@ -1478,6 +1644,15 @@ intel_dp_destroy (struct drm_connector *connector)
        kfree(connector);
 }
 
+static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
+{
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+       i2c_del_adapter(&intel_dp->adapter);
+       drm_encoder_cleanup(encoder);
+       kfree(intel_dp);
+}
+
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
        .dpms = intel_dp_dpms,
        .mode_fixup = intel_dp_mode_fixup,
@@ -1490,20 +1665,21 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .detect = intel_dp_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
+       .set_property = intel_dp_set_property,
        .destroy = intel_dp_destroy,
 };
 
 static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
        .get_modes = intel_dp_get_modes,
        .mode_valid = intel_dp_mode_valid,
-       .best_encoder = intel_attached_encoder,
+       .best_encoder = intel_best_encoder,
 };
 
 static const struct drm_encoder_funcs intel_dp_enc_funcs = {
-       .destroy = intel_encoder_destroy,
+       .destroy = intel_dp_encoder_destroy,
 };
 
-void
+static void
 intel_dp_hot_plug(struct intel_encoder *intel_encoder)
 {
        struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
@@ -1554,6 +1730,20 @@ bool intel_dpd_is_edp(struct drm_device *dev)
        return false;
 }
 
+static void
+intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+
+       intel_dp->force_audio_property =
+               drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2);
+       if (intel_dp->force_audio_property) {
+               intel_dp->force_audio_property->values[0] = -1;
+               intel_dp->force_audio_property->values[1] = 1;
+               drm_connector_attach_property(connector, intel_dp->force_audio_property, 0);
+       }
+}
+
 void
 intel_dp_init(struct drm_device *dev, int output_reg)
 {
@@ -1580,7 +1770,7 @@ 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)) {
+       if (output_reg == DP_A || is_pch_edp(intel_dp)) {
                type = DRM_MODE_CONNECTOR_eDP;
                intel_encoder->type = INTEL_OUTPUT_EDP;
        } else {
@@ -1601,7 +1791,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
        else if (output_reg == DP_D || output_reg == PCH_DP_D)
                intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
 
-       if (IS_eDP(intel_dp))
+       if (is_edp(intel_dp))
                intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
 
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
@@ -1612,12 +1802,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
        intel_dp->has_audio = false;
        intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
 
-       drm_encoder_init(dev, &intel_encoder->enc, &intel_dp_enc_funcs,
+       drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
                         DRM_MODE_ENCODER_TMDS);
-       drm_encoder_helper_add(&intel_encoder->enc, &intel_dp_helper_funcs);
+       drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
 
-       drm_mode_connector_attach_encoder(&intel_connector->base,
-                                         &intel_encoder->enc);
+       intel_connector_attach_encoder(intel_connector, intel_encoder);
        drm_sysfs_connector_add(connector);
 
        /* Set up the DDC bus. */
@@ -1647,10 +1836,29 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
        intel_dp_i2c_init(intel_dp, intel_connector, name);
 
-       intel_encoder->ddc_bus = &intel_dp->adapter;
+       /* Cache some DPCD data in the eDP case */
+       if (is_edp(intel_dp)) {
+               int ret;
+               bool was_on;
+
+               was_on = ironlake_edp_panel_on(intel_dp);
+               ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV,
+                                              intel_dp->dpcd,
+                                              sizeof(intel_dp->dpcd));
+               if (ret == sizeof(intel_dp->dpcd)) {
+                       if (intel_dp->dpcd[0] >= 0x11)
+                               dev_priv->no_aux_handshake = intel_dp->dpcd[3] &
+                                       DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
+               } else {
+                       DRM_ERROR("failed to retrieve link info\n");
+               }
+               if (!was_on)
+                       ironlake_edp_panel_off(dev);
+       }
+
        intel_encoder->hot_plug = intel_dp_hot_plug;
 
-       if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {
+       if (is_edp(intel_dp)) {
                /* initialize panel mode from VBT if available for eDP */
                if (dev_priv->lfp_lvds_vbt_mode) {
                        dev_priv->panel_fixed_mode =
@@ -1662,6 +1870,8 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                }
        }
 
+       intel_dp_add_properties(intel_dp, 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
         * generated on the port when a cable is not attached.