]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/gpu/drm/i915/intel_dp.c
i915: fix ironlake edp panel setup (v4)
[net-next-2.6.git] / drivers / gpu / drm / i915 / intel_dp.c
index 8e283f75941d4de59901e3db34e254ad4480a8f9..1aac59e83bff0c45a0da94e1f083d40d9e30b396 100644 (file)
@@ -48,30 +48,28 @@ struct intel_dp_priv {
        uint32_t output_reg;
        uint32_t DP;
        uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
-       uint32_t save_DP;
-       uint8_t  save_link_configuration[DP_LINK_CONFIGURATION_SIZE];
        bool has_audio;
        int dpms_mode;
        uint8_t link_bw;
        uint8_t lane_count;
        uint8_t dpcd[4];
-       struct intel_output *intel_output;
+       struct intel_encoder *intel_encoder;
        struct i2c_adapter adapter;
        struct i2c_algo_dp_aux_data algo;
 };
 
 static void
-intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
+intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
                    uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]);
 
 static void
-intel_dp_link_down(struct intel_output *intel_output, uint32_t DP);
+intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP);
 
 void
-intel_edp_link_config (struct intel_output *intel_output,
+intel_edp_link_config (struct intel_encoder *intel_encoder,
                int *lane_num, int *link_bw)
 {
-       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
 
        *lane_num = dp_priv->lane_count;
        if (dp_priv->link_bw == DP_LINK_BW_1_62)
@@ -81,9 +79,9 @@ intel_edp_link_config (struct intel_output *intel_output,
 }
 
 static int
-intel_dp_max_lane_count(struct intel_output *intel_output)
+intel_dp_max_lane_count(struct intel_encoder *intel_encoder)
 {
-       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
        int max_lane_count = 4;
 
        if (dp_priv->dpcd[0] >= 0x11) {
@@ -99,9 +97,9 @@ intel_dp_max_lane_count(struct intel_output *intel_output)
 }
 
 static int
-intel_dp_max_link_bw(struct intel_output *intel_output)
+intel_dp_max_link_bw(struct intel_encoder *intel_encoder)
 {
-       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
        int max_link_bw = dp_priv->dpcd[1];
 
        switch (max_link_bw) {
@@ -127,26 +125,36 @@ intel_dp_link_clock(uint8_t link_bw)
 /* I think this is a fiction */
 static int
 intel_dp_link_required(struct drm_device *dev,
-                      struct intel_output *intel_output, int pixel_clock)
+                      struct intel_encoder *intel_encoder, int pixel_clock)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (IS_eDP(intel_output))
+       if (IS_eDP(intel_encoder))
                return (pixel_clock * dev_priv->edp_bpp) / 8;
        else
                return pixel_clock * 3;
 }
 
+static int
+intel_dp_max_data_rate(int max_link_clock, int max_lanes)
+{
+       return (max_link_clock * max_lanes * 8) / 10;
+}
+
 static int
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
 {
-       struct intel_output *intel_output = to_intel_output(connector);
-       int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output));
-       int max_lanes = intel_dp_max_lane_count(intel_output);
-
-       if (intel_dp_link_required(connector->dev, intel_output, mode->clock)
-                       > max_link_clock * max_lanes)
+       struct drm_encoder *encoder = intel_attached_encoder(connector);
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+       int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
+       int max_lanes = intel_dp_max_lane_count(intel_encoder);
+
+       /* 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_encoder) &&
+           (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
+            > intel_dp_max_data_rate(max_link_clock, max_lanes)))
                return MODE_CLOCK_HIGH;
 
        if (mode->clock < 10000)
@@ -209,13 +217,13 @@ intel_hrawclk(struct drm_device *dev)
 }
 
 static int
-intel_dp_aux_ch(struct intel_output *intel_output,
+intel_dp_aux_ch(struct intel_encoder *intel_encoder,
                uint8_t *send, int send_bytes,
                uint8_t *recv, int recv_size)
 {
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        uint32_t output_reg = dp_priv->output_reg;
-       struct drm_device *dev = intel_output->base.dev;
+       struct drm_device *dev = intel_encoder->enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t ch_ctl = output_reg + 0x10;
        uint32_t ch_data = ch_ctl + 4;
@@ -224,19 +232,27 @@ intel_dp_aux_ch(struct intel_output *intel_output,
        uint32_t ctl;
        uint32_t status;
        uint32_t aux_clock_divider;
-       int try;
+       int try, precharge;
 
        /* 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
         */
-       if (IS_eDP(intel_output))
-               aux_clock_divider = 225; /* eDP input clock at 450Mhz */
-       else if (HAS_PCH_SPLIT(dev))
+       if (IS_eDP(intel_encoder)) {
+               if (IS_GEN6(dev))
+                       aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
+               else
+                       aux_clock_divider = 225; /* eDP input clock at 450Mhz */
+       } else if (HAS_PCH_SPLIT(dev))
                aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */
        else
                aux_clock_divider = intel_hrawclk(dev) / 2;
 
+       if (IS_GEN6(dev))
+               precharge = 3;
+       else
+               precharge = 5;
+
        /* Must try at least 3 times according to DP spec */
        for (try = 0; try < 5; try++) {
                /* Load the send data into the aux channel data registers */
@@ -249,7 +265,7 @@ intel_dp_aux_ch(struct intel_output *intel_output,
                ctl = (DP_AUX_CH_CTL_SEND_BUSY |
                       DP_AUX_CH_CTL_TIME_OUT_400us |
                       (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
-                      (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+                      (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
                       (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
                       DP_AUX_CH_CTL_DONE |
                       DP_AUX_CH_CTL_TIME_OUT_ERROR |
@@ -313,7 +329,7 @@ intel_dp_aux_ch(struct intel_output *intel_output,
 
 /* Write data to the aux channel in native mode */
 static int
-intel_dp_aux_native_write(struct intel_output *intel_output,
+intel_dp_aux_native_write(struct intel_encoder *intel_encoder,
                          uint16_t address, uint8_t *send, int send_bytes)
 {
        int ret;
@@ -330,7 +346,7 @@ intel_dp_aux_native_write(struct intel_output *intel_output,
        memcpy(&msg[4], send, send_bytes);
        msg_bytes = send_bytes + 4;
        for (;;) {
-               ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1);
+               ret = intel_dp_aux_ch(intel_encoder, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
                if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
@@ -345,15 +361,15 @@ intel_dp_aux_native_write(struct intel_output *intel_output,
 
 /* Write a single byte to the aux channel in native mode */
 static int
-intel_dp_aux_native_write_1(struct intel_output *intel_output,
+intel_dp_aux_native_write_1(struct intel_encoder *intel_encoder,
                            uint16_t address, uint8_t byte)
 {
-       return intel_dp_aux_native_write(intel_output, address, &byte, 1);
+       return intel_dp_aux_native_write(intel_encoder, address, &byte, 1);
 }
 
 /* read bytes from a native aux channel */
 static int
-intel_dp_aux_native_read(struct intel_output *intel_output,
+intel_dp_aux_native_read(struct intel_encoder *intel_encoder,
                         uint16_t address, uint8_t *recv, int recv_bytes)
 {
        uint8_t msg[4];
@@ -372,7 +388,7 @@ intel_dp_aux_native_read(struct intel_output *intel_output,
        reply_bytes = recv_bytes + 1;
 
        for (;;) {
-               ret = intel_dp_aux_ch(intel_output, msg, msg_bytes,
+               ret = intel_dp_aux_ch(intel_encoder, msg, msg_bytes,
                                      reply, reply_bytes);
                if (ret == 0)
                        return -EPROTO;
@@ -398,7 +414,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
        struct intel_dp_priv *dp_priv = container_of(adapter,
                                                     struct intel_dp_priv,
                                                     adapter);
-       struct intel_output *intel_output = dp_priv->intel_output;
+       struct intel_encoder *intel_encoder = dp_priv->intel_encoder;
        uint16_t address = algo_data->address;
        uint8_t msg[5];
        uint8_t reply[2];
@@ -437,7 +453,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
        }
 
        for (;;) {
-         ret = intel_dp_aux_ch(intel_output,
+         ret = intel_dp_aux_ch(intel_encoder,
                                msg, msg_bytes,
                                reply, reply_bytes);
                if (ret < 0) {
@@ -465,9 +481,10 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 }
 
 static int
-intel_dp_i2c_init(struct intel_output *intel_output, const char *name)
+intel_dp_i2c_init(struct intel_encoder *intel_encoder,
+                 struct intel_connector *intel_connector, const char *name)
 {
-       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
 
        DRM_DEBUG_KMS("i2c_init %s\n", name);
        dp_priv->algo.running = false;
@@ -480,7 +497,7 @@ intel_dp_i2c_init(struct intel_output *intel_output, const char *name)
        strncpy (dp_priv->adapter.name, name, sizeof(dp_priv->adapter.name) - 1);
        dp_priv->adapter.name[sizeof(dp_priv->adapter.name) - 1] = '\0';
        dp_priv->adapter.algo_data = &dp_priv->algo;
-       dp_priv->adapter.dev.parent = &intel_output->base.kdev;
+       dp_priv->adapter.dev.parent = &intel_connector->base.kdev;
        
        return i2c_dp_aux_add_bus(&dp_priv->adapter);
 }
@@ -489,18 +506,18 @@ static bool
 intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                    struct drm_display_mode *adjusted_mode)
 {
-       struct intel_output *intel_output = enc_to_intel_output(encoder);
-       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
        int lane_count, clock;
-       int max_lane_count = intel_dp_max_lane_count(intel_output);
-       int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0;
+       int max_lane_count = intel_dp_max_lane_count(intel_encoder);
+       int max_clock = intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0;
        static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 
        for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
                for (clock = 0; clock <= max_clock; clock++) {
-                       int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
+                       int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
-                       if (intel_dp_link_required(encoder->dev, intel_output, mode->clock)
+                       if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)
                                        <= link_avail) {
                                dp_priv->link_bw = bws[clock];
                                dp_priv->lane_count = lane_count;
@@ -513,6 +530,18 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                        }
                }
        }
+
+       if (IS_eDP(intel_encoder)) {
+               /* okay we failed just pick the highest */
+               dp_priv->lane_count = max_lane_count;
+               dp_priv->link_bw = bws[max_clock];
+               adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+               DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
+                             "count %d clock %d\n",
+                             dp_priv->link_bw, dp_priv->lane_count,
+                             adjusted_mode->clock);
+               return true;
+       }
        return false;
 }
 
@@ -555,23 +584,26 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 {
        struct drm_device *dev = crtc->dev;
        struct drm_mode_config *mode_config = &dev->mode_config;
-       struct drm_connector *connector;
+       struct drm_encoder *encoder;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int lane_count = 4;
        struct intel_dp_m_n m_n;
 
        /*
-        * Find the lane count in the intel_output private
+        * Find the lane count in the intel_encoder private
         */
-       list_for_each_entry(connector, &mode_config->connector_list, head) {
-               struct intel_output *intel_output = to_intel_output(connector);
-               struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       list_for_each_entry(encoder, &mode_config->encoder_list, head) {
+               struct intel_encoder *intel_encoder;
+               struct intel_dp_priv *dp_priv;
 
-               if (!connector->encoder || connector->encoder->crtc != crtc)
+               if (encoder->crtc != crtc)
                        continue;
 
-               if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) {
+               intel_encoder = enc_to_intel_encoder(encoder);
+               dp_priv = intel_encoder->dev_priv;
+
+               if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
                        lane_count = dp_priv->lane_count;
                        break;
                }
@@ -626,16 +658,24 @@ static void
 intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                  struct drm_display_mode *adjusted_mode)
 {
-       struct intel_output *intel_output = enc_to_intel_output(encoder);
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
-       struct drm_crtc *crtc = intel_output->enc.crtc;
+       struct drm_device *dev = encoder->dev;
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
+       struct drm_crtc *crtc = intel_encoder->enc.crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       dp_priv->DP = (DP_LINK_TRAIN_OFF |
-                       DP_VOLTAGE_0_4 |
-                       DP_PRE_EMPHASIS_0 |
-                       DP_SYNC_VS_HIGH |
-                       DP_SYNC_HS_HIGH);
+       dp_priv->DP = (DP_VOLTAGE_0_4 |
+                      DP_PRE_EMPHASIS_0);
+
+       if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+               dp_priv->DP |= DP_SYNC_HS_HIGH;
+       if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+               dp_priv->DP |= DP_SYNC_VS_HIGH;
+
+       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
+               dp_priv->DP |= DP_LINK_TRAIN_OFF_CPT;
+       else
+               dp_priv->DP |= DP_LINK_TRAIN_OFF;
 
        switch (dp_priv->lane_count) {
        case 1:
@@ -656,18 +696,18 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        dp_priv->link_configuration[1] = dp_priv->lane_count;
 
        /*
-        * Check for DPCD version > 1.1,
-        * enable enahanced frame stuff in that case
+        * Check for DPCD version > 1.1 and enhanced framing support
         */
-       if (dp_priv->dpcd[0] >= 0x11) {
+       if (dp_priv->dpcd[0] >= 0x11 && (dp_priv->dpcd[2] & DP_ENHANCED_FRAME_CAP)) {
                dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
                dp_priv->DP |= DP_ENHANCED_FRAMING;
        }
 
-       if (intel_crtc->pipe == 1)
+       /* CPT DP's pipe select is decided in TRANS_DP_CTL */
+       if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
                dp_priv->DP |= DP_PIPEB_SELECT;
 
-       if (IS_eDP(intel_output)) {
+       if (IS_eDP(intel_encoder)) {
                /* don't miss out required setting for eDP */
                dp_priv->DP |= DP_PLL_ENABLE;
                if (adjusted_mode->clock < 200000)
@@ -702,22 +742,22 @@ static void ironlake_edp_backlight_off (struct drm_device *dev)
 static void
 intel_dp_dpms(struct drm_encoder *encoder, int mode)
 {
-       struct intel_output *intel_output = enc_to_intel_output(encoder);
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
-       struct drm_device *dev = intel_output->base.dev;
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
+       struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t dp_reg = I915_READ(dp_priv->output_reg);
 
        if (mode != DRM_MODE_DPMS_ON) {
                if (dp_reg & DP_PORT_EN) {
-                       intel_dp_link_down(intel_output, dp_priv->DP);
-                       if (IS_eDP(intel_output))
+                       intel_dp_link_down(intel_encoder, dp_priv->DP);
+                       if (IS_eDP(intel_encoder))
                                ironlake_edp_backlight_off(dev);
                }
        } else {
                if (!(dp_reg & DP_PORT_EN)) {
-                       intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
-                       if (IS_eDP(intel_output))
+                       intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
+                       if (IS_eDP(intel_encoder))
                                ironlake_edp_backlight_on(dev);
                }
        }
@@ -729,12 +769,12 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
  * link status information
  */
 static bool
-intel_dp_get_link_status(struct intel_output *intel_output,
+intel_dp_get_link_status(struct intel_encoder *intel_encoder,
                         uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
        int ret;
 
-       ret = intel_dp_aux_native_read(intel_output,
+       ret = intel_dp_aux_native_read(intel_encoder,
                                       DP_LANE0_1_STATUS,
                                       link_status, DP_LINK_STATUS_SIZE);
        if (ret != DP_LINK_STATUS_SIZE)
@@ -749,20 +789,6 @@ intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
        return link_status[r - DP_LANE0_1_STATUS];
 }
 
-static void
-intel_dp_save(struct drm_connector *connector)
-{
-       struct intel_output *intel_output = to_intel_output(connector);
-       struct drm_device *dev = intel_output->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
-
-       dp_priv->save_DP = I915_READ(dp_priv->output_reg);
-       intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET,
-                                dp_priv->save_link_configuration,
-                                sizeof (dp_priv->save_link_configuration));
-}
-
 static uint8_t
 intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
                                 int lane)
@@ -825,7 +851,7 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
 }
 
 static void
-intel_get_adjust_train(struct intel_output *intel_output,
+intel_get_adjust_train(struct intel_encoder *intel_encoder,
                       uint8_t link_status[DP_LINK_STATUS_SIZE],
                       int lane_count,
                       uint8_t train_set[4])
@@ -892,6 +918,25 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count)
        return signal_levels;
 }
 
+/* Gen6's DP voltage swing and pre-emphasis control */
+static uint32_t
+intel_gen6_edp_signal_levels(uint8_t train_set)
+{
+       switch (train_set & (DP_TRAIN_VOLTAGE_SWING_MASK|DP_TRAIN_PRE_EMPHASIS_MASK)) {
+       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
+               return EDP_LINK_TRAIN_400MV_0DB_SNB_B;
+       case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
+               return EDP_LINK_TRAIN_400MV_6DB_SNB_B;
+       case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
+               return EDP_LINK_TRAIN_600MV_3_5DB_SNB_B;
+       case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
+               return EDP_LINK_TRAIN_800MV_0DB_SNB_B;
+       default:
+               DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level\n");
+               return EDP_LINK_TRAIN_400MV_0DB_SNB_B;
+       }
+}
+
 static uint8_t
 intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
                      int lane)
@@ -942,15 +987,15 @@ intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
 }
 
 static bool
-intel_dp_set_link_train(struct intel_output *intel_output,
+intel_dp_set_link_train(struct intel_encoder *intel_encoder,
                        uint32_t dp_reg_value,
                        uint8_t dp_train_pat,
                        uint8_t train_set[4],
                        bool first)
 {
-       struct drm_device *dev = intel_output->base.dev;
+       struct drm_device *dev = intel_encoder->enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        int ret;
 
        I915_WRITE(dp_priv->output_reg, dp_reg_value);
@@ -958,11 +1003,11 @@ intel_dp_set_link_train(struct intel_output *intel_output,
        if (first)
                intel_wait_for_vblank(dev);
 
-       intel_dp_aux_native_write_1(intel_output,
+       intel_dp_aux_native_write_1(intel_encoder,
                                    DP_TRAINING_PATTERN_SET,
                                    dp_train_pat);
 
-       ret = intel_dp_aux_native_write(intel_output,
+       ret = intel_dp_aux_native_write(intel_encoder,
                                        DP_TRAINING_LANE0_SET, train_set, 4);
        if (ret != 4)
                return false;
@@ -971,12 +1016,12 @@ intel_dp_set_link_train(struct intel_output *intel_output,
 }
 
 static void
-intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
+intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
                    uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE])
 {
-       struct drm_device *dev = intel_output->base.dev;
+       struct drm_device *dev = intel_encoder->enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        uint8_t train_set[4];
        uint8_t link_status[DP_LINK_STATUS_SIZE];
        int i;
@@ -985,30 +1030,45 @@ intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
        bool channel_eq = false;
        bool first = true;
        int tries;
+       u32 reg;
 
        /* Write the link configuration data */
-       intel_dp_aux_native_write(intel_output, 0x100,
+       intel_dp_aux_native_write(intel_encoder, DP_LINK_BW_SET,
                                  link_configuration, DP_LINK_CONFIGURATION_SIZE);
 
        DP |= DP_PORT_EN;
-       DP &= ~DP_LINK_TRAIN_MASK;
+       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
+               DP &= ~DP_LINK_TRAIN_MASK_CPT;
+       else
+               DP &= ~DP_LINK_TRAIN_MASK;
        memset(train_set, 0, 4);
        voltage = 0xff;
        tries = 0;
        clock_recovery = false;
        for (;;) {
                /* Use train_set[0] to set the voltage and pre emphasis values */
-               uint32_t    signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
-               DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+               uint32_t    signal_levels;
+               if (IS_GEN6(dev) && IS_eDP(intel_encoder)) {
+                       signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
+                       DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
+               } else {
+                       signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
+                       DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+               }
 
-               if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1,
+               if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
+                       reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
+               else
+                       reg = DP | DP_LINK_TRAIN_PAT_1;
+
+               if (!intel_dp_set_link_train(intel_encoder, reg,
                                             DP_TRAINING_PATTERN_1, train_set, first))
                        break;
                first = false;
                /* Set training pattern 1 */
 
                udelay(100);
-               if (!intel_dp_get_link_status(intel_output, link_status))
+               if (!intel_dp_get_link_status(intel_encoder, link_status))
                        break;
 
                if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) {
@@ -1033,7 +1093,7 @@ intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
                voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
                /* Compute new train_set as requested by target */
-               intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
+               intel_get_adjust_train(intel_encoder, link_status, dp_priv->lane_count, train_set);
        }
 
        /* channel equalization */
@@ -1041,17 +1101,29 @@ intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
        channel_eq = false;
        for (;;) {
                /* Use train_set[0] to set the voltage and pre emphasis values */
-               uint32_t    signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
-               DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+               uint32_t    signal_levels;
+
+               if (IS_GEN6(dev) && IS_eDP(intel_encoder)) {
+                       signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
+                       DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
+               } else {
+                       signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
+                       DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+               }
+
+               if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
+                       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_output, DP | DP_LINK_TRAIN_PAT_2,
+               if (!intel_dp_set_link_train(intel_encoder, reg,
                                             DP_TRAINING_PATTERN_2, train_set,
                                             false))
                        break;
 
                udelay(400);
-               if (!intel_dp_get_link_status(intel_output, link_status))
+               if (!intel_dp_get_link_status(intel_encoder, link_status))
                        break;
 
                if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) {
@@ -1064,56 +1136,55 @@ intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
                        break;
 
                /* Compute new train_set as requested by target */
-               intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
+               intel_get_adjust_train(intel_encoder, link_status, dp_priv->lane_count, train_set);
                ++tries;
        }
 
-       I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF);
+       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
+               reg = DP | DP_LINK_TRAIN_OFF_CPT;
+       else
+               reg = DP | DP_LINK_TRAIN_OFF;
+
+       I915_WRITE(dp_priv->output_reg, reg);
        POSTING_READ(dp_priv->output_reg);
-       intel_dp_aux_native_write_1(intel_output,
+       intel_dp_aux_native_write_1(intel_encoder,
                                    DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
 }
 
 static void
-intel_dp_link_down(struct intel_output *intel_output, uint32_t DP)
+intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP)
 {
-       struct drm_device *dev = intel_output->base.dev;
+       struct drm_device *dev = intel_encoder->enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
 
        DRM_DEBUG_KMS("\n");
 
-       if (IS_eDP(intel_output)) {
+       if (IS_eDP(intel_encoder)) {
                DP &= ~DP_PLL_ENABLE;
                I915_WRITE(dp_priv->output_reg, DP);
                POSTING_READ(dp_priv->output_reg);
                udelay(100);
        }
 
-       DP &= ~DP_LINK_TRAIN_MASK;
-       I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
-       POSTING_READ(dp_priv->output_reg);
+       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) {
+               DP &= ~DP_LINK_TRAIN_MASK_CPT;
+               I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
+               POSTING_READ(dp_priv->output_reg);
+       } else {
+               DP &= ~DP_LINK_TRAIN_MASK;
+               I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
+               POSTING_READ(dp_priv->output_reg);
+       }
 
        udelay(17000);
 
-       if (IS_eDP(intel_output))
+       if (IS_eDP(intel_encoder))
                DP |= DP_LINK_TRAIN_OFF;
        I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN);
        POSTING_READ(dp_priv->output_reg);
 }
 
-static void
-intel_dp_restore(struct drm_connector *connector)
-{
-       struct intel_output *intel_output = to_intel_output(connector);
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
-
-       if (dp_priv->save_DP & DP_PORT_EN)
-               intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration);
-       else
-               intel_dp_link_down(intel_output,  dp_priv->save_DP);
-}
-
 /*
  * According to DP spec
  * 5.1.2:
@@ -1124,38 +1195,41 @@ intel_dp_restore(struct drm_connector *connector)
  */
 
 static void
-intel_dp_check_link_status(struct intel_output *intel_output)
+intel_dp_check_link_status(struct intel_encoder *intel_encoder)
 {
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        uint8_t link_status[DP_LINK_STATUS_SIZE];
 
-       if (!intel_output->enc.crtc)
+       if (!intel_encoder->enc.crtc)
                return;
 
-       if (!intel_dp_get_link_status(intel_output, link_status)) {
-               intel_dp_link_down(intel_output, dp_priv->DP);
+       if (!intel_dp_get_link_status(intel_encoder, link_status)) {
+               intel_dp_link_down(intel_encoder, dp_priv->DP);
                return;
        }
 
        if (!intel_channel_eq_ok(link_status, dp_priv->lane_count))
-               intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
+               intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
 }
 
 static enum drm_connector_status
 ironlake_dp_detect(struct drm_connector *connector)
 {
-       struct intel_output *intel_output = to_intel_output(connector);
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct drm_encoder *encoder = intel_attached_encoder(connector);
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        enum drm_connector_status status;
 
        status = connector_status_disconnected;
-       if (intel_dp_aux_native_read(intel_output,
+       if (intel_dp_aux_native_read(intel_encoder,
                                     0x000, dp_priv->dpcd,
                                     sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
        {
                if (dp_priv->dpcd[0] != 0)
                        status = connector_status_connected;
        }
+       DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", dp_priv->dpcd[0],
+                     dp_priv->dpcd[1], dp_priv->dpcd[2], dp_priv->dpcd[3]);
        return status;
 }
 
@@ -1168,10 +1242,11 @@ ironlake_dp_detect(struct drm_connector *connector)
 static enum drm_connector_status
 intel_dp_detect(struct drm_connector *connector)
 {
-       struct intel_output *intel_output = to_intel_output(connector);
-       struct drm_device *dev = intel_output->base.dev;
+       struct drm_encoder *encoder = intel_attached_encoder(connector);
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+       struct drm_device *dev = intel_encoder->enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        uint32_t temp, bit;
        enum drm_connector_status status;
 
@@ -1180,16 +1255,6 @@ intel_dp_detect(struct drm_connector *connector)
        if (HAS_PCH_SPLIT(dev))
                return ironlake_dp_detect(connector);
 
-       temp = I915_READ(PORT_HOTPLUG_EN);
-
-       I915_WRITE(PORT_HOTPLUG_EN,
-              temp |
-              DPB_HOTPLUG_INT_EN |
-              DPC_HOTPLUG_INT_EN |
-              DPD_HOTPLUG_INT_EN);
-
-       POSTING_READ(PORT_HOTPLUG_EN);
-
        switch (dp_priv->output_reg) {
        case DP_B:
                bit = DPB_HOTPLUG_INT_STATUS;
@@ -1210,7 +1275,7 @@ intel_dp_detect(struct drm_connector *connector)
                return connector_status_disconnected;
 
        status = connector_status_disconnected;
-       if (intel_dp_aux_native_read(intel_output,
+       if (intel_dp_aux_native_read(intel_encoder,
                                     0x000, dp_priv->dpcd,
                                     sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
        {
@@ -1222,20 +1287,21 @@ intel_dp_detect(struct drm_connector *connector)
 
 static int intel_dp_get_modes(struct drm_connector *connector)
 {
-       struct intel_output *intel_output = to_intel_output(connector);
-       struct drm_device *dev = intel_output->base.dev;
+       struct drm_encoder *encoder = intel_attached_encoder(connector);
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+       struct drm_device *dev = intel_encoder->enc.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(intel_output);
+       ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
        if (ret)
                return ret;
 
        /* if eDP has no EDID, try to use fixed panel mode from VBT */
-       if (IS_eDP(intel_output)) {
+       if (IS_eDP(intel_encoder)) {
                if (dev_priv->panel_fixed_mode != NULL) {
                        struct drm_display_mode *mode;
                        mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
@@ -1249,13 +1315,9 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 static void
 intel_dp_destroy (struct drm_connector *connector)
 {
-       struct intel_output *intel_output = to_intel_output(connector);
-
-       if (intel_output->i2c_bus)
-               intel_i2c_destroy(intel_output->i2c_bus);
        drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
-       kfree(intel_output);
+       kfree(connector);
 }
 
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
@@ -1268,8 +1330,6 @@ static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
-       .save = intel_dp_save,
-       .restore = intel_dp_restore,
        .detect = intel_dp_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = intel_dp_destroy,
@@ -1278,12 +1338,17 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = {
 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_best_encoder,
+       .best_encoder = intel_attached_encoder,
 };
 
 static void intel_dp_enc_destroy(struct drm_encoder *encoder)
 {
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+
+       if (intel_encoder->i2c_bus)
+               intel_i2c_destroy(intel_encoder->i2c_bus);
        drm_encoder_cleanup(encoder);
+       kfree(intel_encoder);
 }
 
 static const struct drm_encoder_funcs intel_dp_enc_funcs = {
@@ -1291,12 +1356,34 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
 };
 
 void
-intel_dp_hot_plug(struct intel_output *intel_output)
+intel_dp_hot_plug(struct intel_encoder *intel_encoder)
 {
-       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
 
        if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON)
-               intel_dp_check_link_status(intel_output);
+               intel_dp_check_link_status(intel_encoder);
+}
+
+/* Return which DP Port should be selected for Transcoder DP control */
+int
+intel_trans_dp_port_sel (struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_encoder *encoder;
+       struct intel_encoder *intel_encoder = NULL;
+
+       list_for_each_entry(encoder, &mode_config->encoder_list, head) {
+               if (encoder->crtc != crtc)
+                       continue;
+
+               intel_encoder = enc_to_intel_encoder(encoder);
+               if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
+                       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
+                       return dp_priv->output_reg;
+               }
+       }
+       return -1;
 }
 
 void
@@ -1304,53 +1391,62 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_connector *connector;
-       struct intel_output *intel_output;
+       struct intel_encoder *intel_encoder;
+       struct intel_connector *intel_connector;
        struct intel_dp_priv *dp_priv;
        const char *name = NULL;
 
-       intel_output = kcalloc(sizeof(struct intel_output) + 
+       intel_encoder = kcalloc(sizeof(struct intel_encoder) +
                               sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
-       if (!intel_output)
+       if (!intel_encoder)
                return;
 
-       dp_priv = (struct intel_dp_priv *)(intel_output + 1);
+       intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+       if (!intel_connector) {
+               kfree(intel_encoder);
+               return;
+       }
 
-       connector = &intel_output->base;
+       dp_priv = (struct intel_dp_priv *)(intel_encoder + 1);
+
+       connector = &intel_connector->base;
        drm_connector_init(dev, connector, &intel_dp_connector_funcs,
                           DRM_MODE_CONNECTOR_DisplayPort);
        drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
 
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
+
        if (output_reg == DP_A)
-               intel_output->type = INTEL_OUTPUT_EDP;
+               intel_encoder->type = INTEL_OUTPUT_EDP;
        else
-               intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
+               intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 
        if (output_reg == DP_B || output_reg == PCH_DP_B)
-               intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
+               intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
        else if (output_reg == DP_C || output_reg == PCH_DP_C)
-               intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
+               intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
        else if (output_reg == DP_D || output_reg == PCH_DP_D)
-               intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+               intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
 
-       if (IS_eDP(intel_output))
-               intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
+       if (IS_eDP(intel_encoder))
+               intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
 
-       intel_output->crtc_mask = (1 << 0) | (1 << 1);
+       intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
        connector->interlace_allowed = true;
        connector->doublescan_allowed = 0;
 
-       dp_priv->intel_output = intel_output;
+       dp_priv->intel_encoder = intel_encoder;
        dp_priv->output_reg = output_reg;
        dp_priv->has_audio = false;
        dp_priv->dpms_mode = DRM_MODE_DPMS_ON;
-       intel_output->dev_priv = dp_priv;
+       intel_encoder->dev_priv = dp_priv;
 
-       drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs,
+       drm_encoder_init(dev, &intel_encoder->enc, &intel_dp_enc_funcs,
                         DRM_MODE_ENCODER_TMDS);
-       drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs);
+       drm_encoder_helper_add(&intel_encoder->enc, &intel_dp_helper_funcs);
 
-       drm_mode_connector_attach_encoder(&intel_output->base,
-                                         &intel_output->enc);
+       drm_mode_connector_attach_encoder(&intel_connector->base,
+                                         &intel_encoder->enc);
        drm_sysfs_connector_add(connector);
 
        /* Set up the DDC bus. */
@@ -1378,10 +1474,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                        break;
        }
 
-       intel_dp_i2c_init(intel_output, name);
+       intel_dp_i2c_init(intel_encoder, intel_connector, name);
 
-       intel_output->ddc_bus = &dp_priv->adapter;
-       intel_output->hot_plug = intel_dp_hot_plug;
+       intel_encoder->ddc_bus = &dp_priv->adapter;
+       intel_encoder->hot_plug = intel_dp_hot_plug;
 
        if (output_reg == DP_A) {
                /* initialize panel mode from VBT if available for eDP */