]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/gpu/drm/i915/intel_dp.c
drm/i915: eDP mode set sequence corrections
[net-next-2.6.git] / drivers / gpu / drm / i915 / intel_dp.c
index 40be1fa65be18fa730347b3da0f248a2b35b19e6..8061a48804a31cbb8fe550c1a07538ac514fa94e 100644 (file)
 
 #define DP_LINK_CONFIGURATION_SIZE     9
 
-#define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
-#define IS_PCH_eDP(dp_priv) ((dp_priv)->is_pch_edp)
+#define IS_eDP(i) ((i)->base.type == INTEL_OUTPUT_EDP)
+#define IS_PCH_eDP(i) ((i)->is_pch_edp)
 
-struct intel_dp_priv {
+struct intel_dp {
+       struct intel_encoder base;
        uint32_t output_reg;
        uint32_t DP;
        uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
@@ -54,40 +55,39 @@ struct intel_dp_priv {
        uint8_t link_bw;
        uint8_t lane_count;
        uint8_t dpcd[4];
-       struct intel_encoder *intel_encoder;
        struct i2c_adapter adapter;
        struct i2c_algo_dp_aux_data algo;
        bool is_pch_edp;
 };
 
-static void
-intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
-                   uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]);
+static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
+{
+       return container_of(enc_to_intel_encoder(encoder), struct intel_dp, base);
+}
 
-static void
-intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP);
+static void intel_dp_link_train(struct intel_dp *intel_dp);
+static void intel_dp_link_down(struct intel_dp *intel_dp);
 
 void
 intel_edp_link_config (struct intel_encoder *intel_encoder,
-               int *lane_num, int *link_bw)
+                      int *lane_num, int *link_bw)
 {
-       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
+       struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
 
-       *lane_num = dp_priv->lane_count;
-       if (dp_priv->link_bw == DP_LINK_BW_1_62)
+       *lane_num = intel_dp->lane_count;
+       if (intel_dp->link_bw == DP_LINK_BW_1_62)
                *link_bw = 162000;
-       else if (dp_priv->link_bw == DP_LINK_BW_2_7)
+       else if (intel_dp->link_bw == DP_LINK_BW_2_7)
                *link_bw = 270000;
 }
 
 static int
-intel_dp_max_lane_count(struct intel_encoder *intel_encoder)
+intel_dp_max_lane_count(struct intel_dp *intel_dp)
 {
-       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
        int max_lane_count = 4;
 
-       if (dp_priv->dpcd[0] >= 0x11) {
-               max_lane_count = dp_priv->dpcd[2] & 0x1f;
+       if (intel_dp->dpcd[0] >= 0x11) {
+               max_lane_count = intel_dp->dpcd[2] & 0x1f;
                switch (max_lane_count) {
                case 1: case 2: case 4:
                        break;
@@ -99,10 +99,9 @@ intel_dp_max_lane_count(struct intel_encoder *intel_encoder)
 }
 
 static int
-intel_dp_max_link_bw(struct intel_encoder *intel_encoder)
+intel_dp_max_link_bw(struct intel_dp *intel_dp)
 {
-       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
-       int max_link_bw = dp_priv->dpcd[1];
+       int max_link_bw = intel_dp->dpcd[1];
 
        switch (max_link_bw) {
        case DP_LINK_BW_1_62:
@@ -126,13 +125,11 @@ 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_encoder *intel_encoder, int pixel_clock)
+intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
 
-       if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
+       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
                return (pixel_clock * dev_priv->edp_bpp) / 8;
        else
                return pixel_clock * 3;
@@ -149,14 +146,13 @@ intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
 {
        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;
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        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_encoder));
-       int max_lanes = intel_dp_max_lane_count(intel_encoder);
+       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_encoder) || IS_PCH_eDP(dp_priv)) &&
+       if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
            dev_priv->panel_fixed_mode) {
                if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay)
                        return MODE_PANEL;
@@ -167,8 +163,8 @@ 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_encoder) &&
-           (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
+       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;
 
@@ -232,13 +228,12 @@ intel_hrawclk(struct drm_device *dev)
 }
 
 static int
-intel_dp_aux_ch(struct intel_encoder *intel_encoder,
+intel_dp_aux_ch(struct intel_dp *intel_dp,
                uint8_t *send, int send_bytes,
                uint8_t *recv, int recv_size)
 {
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
-       uint32_t output_reg = dp_priv->output_reg;
-       struct drm_device *dev = intel_encoder->enc.dev;
+       uint32_t output_reg = intel_dp->output_reg;
+       struct drm_device *dev = intel_dp->base.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;
@@ -253,7 +248,7 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder,
         * and would like to run at 2MHz. So, take the
         * hrawclk value and divide by 2 and use that
         */
-       if (IS_eDP(intel_encoder)) {
+       if (IS_eDP(intel_dp)) {
                if (IS_GEN6(dev))
                        aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
                else
@@ -344,7 +339,7 @@ intel_dp_aux_ch(struct intel_encoder *intel_encoder,
 
 /* Write data to the aux channel in native mode */
 static int
-intel_dp_aux_native_write(struct intel_encoder *intel_encoder,
+intel_dp_aux_native_write(struct intel_dp *intel_dp,
                          uint16_t address, uint8_t *send, int send_bytes)
 {
        int ret;
@@ -361,7 +356,7 @@ intel_dp_aux_native_write(struct intel_encoder *intel_encoder,
        memcpy(&msg[4], send, send_bytes);
        msg_bytes = send_bytes + 4;
        for (;;) {
-               ret = intel_dp_aux_ch(intel_encoder, msg, msg_bytes, &ack, 1);
+               ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
                if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
@@ -376,15 +371,15 @@ intel_dp_aux_native_write(struct intel_encoder *intel_encoder,
 
 /* Write a single byte to the aux channel in native mode */
 static int
-intel_dp_aux_native_write_1(struct intel_encoder *intel_encoder,
+intel_dp_aux_native_write_1(struct intel_dp *intel_dp,
                            uint16_t address, uint8_t byte)
 {
-       return intel_dp_aux_native_write(intel_encoder, address, &byte, 1);
+       return intel_dp_aux_native_write(intel_dp, address, &byte, 1);
 }
 
 /* read bytes from a native aux channel */
 static int
-intel_dp_aux_native_read(struct intel_encoder *intel_encoder,
+intel_dp_aux_native_read(struct intel_dp *intel_dp,
                         uint16_t address, uint8_t *recv, int recv_bytes)
 {
        uint8_t msg[4];
@@ -403,7 +398,7 @@ intel_dp_aux_native_read(struct intel_encoder *intel_encoder,
        reply_bytes = recv_bytes + 1;
 
        for (;;) {
-               ret = intel_dp_aux_ch(intel_encoder, msg, msg_bytes,
+               ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
                                      reply, reply_bytes);
                if (ret == 0)
                        return -EPROTO;
@@ -426,10 +421,9 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                    uint8_t write_byte, uint8_t *read_byte)
 {
        struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-       struct intel_dp_priv *dp_priv = container_of(adapter,
-                                                    struct intel_dp_priv,
-                                                    adapter);
-       struct intel_encoder *intel_encoder = dp_priv->intel_encoder;
+       struct intel_dp *intel_dp = container_of(adapter,
+                                               struct intel_dp,
+                                               adapter);
        uint16_t address = algo_data->address;
        uint8_t msg[5];
        uint8_t reply[2];
@@ -468,7 +462,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
        }
 
        for (;;) {
-         ret = intel_dp_aux_ch(intel_encoder,
+         ret = intel_dp_aux_ch(intel_dp,
                                msg, msg_bytes,
                                reply, reply_bytes);
                if (ret < 0) {
@@ -496,57 +490,42 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 }
 
 static int
-intel_dp_i2c_init(struct intel_encoder *intel_encoder,
+intel_dp_i2c_init(struct intel_dp *intel_dp,
                  struct intel_connector *intel_connector, const char *name)
 {
-       struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
-
        DRM_DEBUG_KMS("i2c_init %s\n", name);
-       dp_priv->algo.running = false;
-       dp_priv->algo.address = 0;
-       dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch;
-
-       memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter));
-       dp_priv->adapter.owner = THIS_MODULE;
-       dp_priv->adapter.class = I2C_CLASS_DDC;
-       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_connector->base.kdev;
-       
-       return i2c_dp_aux_add_bus(&dp_priv->adapter);
+       intel_dp->algo.running = false;
+       intel_dp->algo.address = 0;
+       intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch;
+
+       memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
+       intel_dp->adapter.owner = THIS_MODULE;
+       intel_dp->adapter.class = I2C_CLASS_DDC;
+       strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
+       intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
+       intel_dp->adapter.algo_data = &intel_dp->algo;
+       intel_dp->adapter.dev.parent = &intel_connector->base.kdev;
+
+       return i2c_dp_aux_add_bus(&intel_dp->adapter);
 }
 
 static bool
 intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                    struct drm_display_mode *adjusted_mode)
 {
-       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;
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        int lane_count, clock;
-       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;
+       int max_lane_count = intel_dp_max_lane_count(intel_dp);
+       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_encoder) || IS_PCH_eDP(dp_priv)) &&
+       if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
            dev_priv->panel_fixed_mode) {
-               struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
-
-               adjusted_mode->hdisplay = fixed_mode->hdisplay;
-               adjusted_mode->hsync_start = fixed_mode->hsync_start;
-               adjusted_mode->hsync_end = fixed_mode->hsync_end;
-               adjusted_mode->htotal = fixed_mode->htotal;
-
-               adjusted_mode->vdisplay = fixed_mode->vdisplay;
-               adjusted_mode->vsync_start = fixed_mode->vsync_start;
-               adjusted_mode->vsync_end = fixed_mode->vsync_end;
-               adjusted_mode->vtotal = fixed_mode->vtotal;
-
-               adjusted_mode->clock = fixed_mode->clock;
-               drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-
+               intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode);
+               intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
+                                       mode, adjusted_mode);
                /*
                 * the mode->clock is used to calculate the Data&Link M/N
                 * of the pipe. For the eDP the fixed clock should be used.
@@ -558,31 +537,33 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                for (clock = 0; clock <= max_clock; clock++) {
                        int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
-                       if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)
+                       if (intel_dp_link_required(encoder->dev, intel_dp, mode->clock)
                                        <= link_avail) {
-                               dp_priv->link_bw = bws[clock];
-                               dp_priv->lane_count = lane_count;
-                               adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+                               intel_dp->link_bw = bws[clock];
+                               intel_dp->lane_count = lane_count;
+                               adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
                                DRM_DEBUG_KMS("Display port link bw %02x lane "
                                                "count %d clock %d\n",
-                                      dp_priv->link_bw, dp_priv->lane_count,
+                                      intel_dp->link_bw, intel_dp->lane_count,
                                       adjusted_mode->clock);
                                return true;
                        }
                }
        }
 
-       if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
+       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
                /* 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);
+               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",
-                             dp_priv->link_bw, dp_priv->lane_count,
+                             intel_dp->link_bw, intel_dp->lane_count,
                              adjusted_mode->clock);
+
                return true;
        }
+
        return false;
 }
 
@@ -626,17 +607,14 @@ bool intel_pch_has_edp(struct drm_crtc *crtc)
        struct drm_encoder *encoder;
 
        list_for_each_entry(encoder, &mode_config->encoder_list, head) {
-               struct intel_encoder *intel_encoder;
-               struct intel_dp_priv *dp_priv;
+               struct intel_dp *intel_dp;
 
-               if (!encoder || encoder->crtc != crtc)
+               if (encoder->crtc != crtc)
                        continue;
 
-               intel_encoder = enc_to_intel_encoder(encoder);
-               dp_priv = intel_encoder->dev_priv;
-
-               if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT)
-                       return dp_priv->is_pch_edp;
+               intel_dp = enc_to_intel_dp(encoder);
+               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
+                       return intel_dp->is_pch_edp;
        }
        return false;
 }
@@ -657,18 +635,15 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
         * Find the lane count in the intel_encoder private
         */
        list_for_each_entry(encoder, &mode_config->encoder_list, head) {
-               struct intel_encoder *intel_encoder;
-               struct intel_dp_priv *dp_priv;
+               struct intel_dp *intel_dp;
 
                if (encoder->crtc != crtc)
                        continue;
 
-               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;
-                       if (IS_PCH_eDP(dp_priv))
+               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;
                }
@@ -724,107 +699,114 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                  struct drm_display_mode *adjusted_mode)
 {
        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_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct drm_crtc *crtc = intel_dp->base.enc.crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       dp_priv->DP = (DP_VOLTAGE_0_4 |
+       intel_dp->DP = (DP_VOLTAGE_0_4 |
                       DP_PRE_EMPHASIS_0);
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-               dp_priv->DP |= DP_SYNC_HS_HIGH;
+               intel_dp->DP |= DP_SYNC_HS_HIGH;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-               dp_priv->DP |= DP_SYNC_VS_HIGH;
+               intel_dp->DP |= DP_SYNC_VS_HIGH;
 
-       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
-               dp_priv->DP |= DP_LINK_TRAIN_OFF_CPT;
+       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
+               intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
        else
-               dp_priv->DP |= DP_LINK_TRAIN_OFF;
+               intel_dp->DP |= DP_LINK_TRAIN_OFF;
 
-       switch (dp_priv->lane_count) {
+       switch (intel_dp->lane_count) {
        case 1:
-               dp_priv->DP |= DP_PORT_WIDTH_1;
+               intel_dp->DP |= DP_PORT_WIDTH_1;
                break;
        case 2:
-               dp_priv->DP |= DP_PORT_WIDTH_2;
+               intel_dp->DP |= DP_PORT_WIDTH_2;
                break;
        case 4:
-               dp_priv->DP |= DP_PORT_WIDTH_4;
+               intel_dp->DP |= DP_PORT_WIDTH_4;
                break;
        }
-       if (dp_priv->has_audio)
-               dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE;
+       if (intel_dp->has_audio)
+               intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
 
-       memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
-       dp_priv->link_configuration[0] = dp_priv->link_bw;
-       dp_priv->link_configuration[1] = dp_priv->lane_count;
+       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;
 
        /*
         * Check for DPCD version > 1.1 and enhanced framing support
         */
-       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_dp->dpcd[0] >= 0x11 && (intel_dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)) {
+               intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+               intel_dp->DP |= DP_ENHANCED_FRAMING;
        }
 
        /* 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;
+               intel_dp->DP |= DP_PIPEB_SELECT;
 
-       if (IS_eDP(intel_encoder)) {
+       if (IS_eDP(intel_dp)) {
                /* don't miss out required setting for eDP */
-               dp_priv->DP |= DP_PLL_ENABLE;
+               intel_dp->DP |= DP_PLL_ENABLE;
                if (adjusted_mode->clock < 200000)
-                       dp_priv->DP |= DP_PLL_FREQ_160MHZ;
+                       intel_dp->DP |= DP_PLL_FREQ_160MHZ;
                else
-                       dp_priv->DP |= DP_PLL_FREQ_270MHZ;
+                       intel_dp->DP |= DP_PLL_FREQ_270MHZ;
        }
 }
 
 static void ironlake_edp_panel_on (struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long timeout = jiffies + msecs_to_jiffies(5000);
-       u32 pp, pp_status;
+       u32 pp;
 
-       pp_status = I915_READ(PCH_PP_STATUS);
-       if (pp_status & PP_ON)
+       if (I915_READ(PCH_PP_STATUS) & PP_ON)
                return;
 
        pp = I915_READ(PCH_PP_CONTROL);
+
+       /* ILK workaround: disable reset around power sequence */
+       pp &= ~PANEL_POWER_RESET;
+       I915_WRITE(PCH_PP_CONTROL, pp);
+       POSTING_READ(PCH_PP_CONTROL);
+
        pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
        I915_WRITE(PCH_PP_CONTROL, pp);
-       do {
-               pp_status = I915_READ(PCH_PP_STATUS);
-       } while (((pp_status & PP_ON) == 0) && !time_after(jiffies, timeout));
 
-       if (time_after(jiffies, timeout))
-               DRM_DEBUG_KMS("panel on wait timed out: 0x%08x\n", pp_status);
+       if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000, 10))
+               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);
 }
 
 static void ironlake_edp_panel_off (struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long timeout = jiffies + msecs_to_jiffies(5000);
-       u32 pp, pp_status;
+       u32 pp;
 
        pp = I915_READ(PCH_PP_CONTROL);
+
+       /* ILK workaround: disable reset around power sequence */
+       pp &= ~PANEL_POWER_RESET;
+       I915_WRITE(PCH_PP_CONTROL, pp);
+       POSTING_READ(PCH_PP_CONTROL);
+
        pp &= ~POWER_TARGET_ON;
        I915_WRITE(PCH_PP_CONTROL, pp);
-       do {
-               pp_status = I915_READ(PCH_PP_STATUS);
-       } while ((pp_status & PP_ON) && !time_after(jiffies, timeout));
 
-       if (time_after(jiffies, timeout))
-               DRM_DEBUG_KMS("panel off wait timed out\n");
+       if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000, 10))
+               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;
+       pp |= EDP_FORCE_VDD | PANEL_POWER_RESET; /* restore panel reset bit */
        I915_WRITE(PCH_PP_CONTROL, pp);
+       POSTING_READ(PCH_PP_CONTROL);
 }
 
 static void ironlake_edp_backlight_on (struct drm_device *dev)
@@ -852,30 +834,28 @@ static void ironlake_edp_backlight_off (struct drm_device *dev)
 static void
 intel_dp_dpms(struct drm_encoder *encoder, int mode)
 {
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
+       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(dp_priv->output_reg);
+       uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
        if (mode != DRM_MODE_DPMS_ON) {
-               if (dp_reg & DP_PORT_EN) {
-                       intel_dp_link_down(intel_encoder, dp_priv->DP);
-                       if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
-                               ironlake_edp_backlight_off(dev);
-                               ironlake_edp_panel_off(dev);
-                       }
+               if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
+                       ironlake_edp_backlight_off(dev);
+                       ironlake_edp_panel_off(dev);
                }
+               if (dp_reg & DP_PORT_EN)
+                       intel_dp_link_down(intel_dp);
        } else {
                if (!(dp_reg & DP_PORT_EN)) {
-                       intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
-                       if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
+                       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);
-                       }
                }
        }
-       dp_priv->dpms_mode = mode;
+       intel_dp->dpms_mode = mode;
 }
 
 /*
@@ -883,12 +863,12 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
  * link status information
  */
 static bool
-intel_dp_get_link_status(struct intel_encoder *intel_encoder,
+intel_dp_get_link_status(struct intel_dp *intel_dp,
                         uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
        int ret;
 
-       ret = intel_dp_aux_native_read(intel_encoder,
+       ret = intel_dp_aux_native_read(intel_dp,
                                       DP_LANE0_1_STATUS,
                                       link_status, DP_LINK_STATUS_SIZE);
        if (ret != DP_LINK_STATUS_SIZE)
@@ -965,7 +945,7 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
 }
 
 static void
-intel_get_adjust_train(struct intel_encoder *intel_encoder,
+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])
@@ -1101,27 +1081,26 @@ intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
 }
 
 static bool
-intel_dp_set_link_train(struct intel_encoder *intel_encoder,
+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],
                        bool first)
 {
-       struct drm_device *dev = intel_encoder->enc.dev;
+       struct drm_device *dev = intel_dp->base.enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        int ret;
 
-       I915_WRITE(dp_priv->output_reg, dp_reg_value);
-       POSTING_READ(dp_priv->output_reg);
+       I915_WRITE(intel_dp->output_reg, dp_reg_value);
+       POSTING_READ(intel_dp->output_reg);
        if (first)
                intel_wait_for_vblank(dev);
 
-       intel_dp_aux_native_write_1(intel_encoder,
+       intel_dp_aux_native_write_1(intel_dp,
                                    DP_TRAINING_PATTERN_SET,
                                    dp_train_pat);
 
-       ret = intel_dp_aux_native_write(intel_encoder,
+       ret = intel_dp_aux_native_write(intel_dp,
                                        DP_TRAINING_LANE0_SET, train_set, 4);
        if (ret != 4)
                return false;
@@ -1130,12 +1109,10 @@ intel_dp_set_link_train(struct intel_encoder *intel_encoder,
 }
 
 static void
-intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
-                   uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE])
+intel_dp_link_train(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = intel_encoder->enc.dev;
+       struct drm_device *dev = intel_dp->base.enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       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;
@@ -1145,13 +1122,15 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
        bool first = true;
        int tries;
        u32 reg;
+       uint32_t DP = intel_dp->DP;
 
        /* Write the link configuration data */
-       intel_dp_aux_native_write(intel_encoder, DP_LINK_BW_SET,
-                                 link_configuration, DP_LINK_CONFIGURATION_SIZE);
+       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_encoder))
+       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
                DP &= ~DP_LINK_TRAIN_MASK_CPT;
        else
                DP &= ~DP_LINK_TRAIN_MASK;
@@ -1162,39 +1141,39 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
        for (;;) {
                /* Use train_set[0] to set the voltage and pre emphasis values */
                uint32_t    signal_levels;
-               if (IS_GEN6(dev) && IS_eDP(intel_encoder)) {
+               if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
                        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);
+                       signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
-               if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
+               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_encoder, reg,
+               if (!intel_dp_set_link_train(intel_dp, reg,
                                             DP_TRAINING_PATTERN_1, train_set, first))
                        break;
                first = false;
                /* Set training pattern 1 */
 
                udelay(100);
-               if (!intel_dp_get_link_status(intel_encoder, link_status))
+               if (!intel_dp_get_link_status(intel_dp, link_status))
                        break;
 
-               if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) {
+               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 < dp_priv->lane_count; i++)
+               for (i = 0; i < intel_dp->lane_count; i++)
                        if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
-               if (i == dp_priv->lane_count)
+               if (i == intel_dp->lane_count)
                        break;
 
                /* Check to see if we've tried the same voltage 5 times */
@@ -1207,7 +1186,7 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, 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_encoder, link_status, dp_priv->lane_count, train_set);
+               intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
        }
 
        /* channel equalization */
@@ -1217,30 +1196,30 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
                /* Use train_set[0] to set the voltage and pre emphasis values */
                uint32_t    signal_levels;
 
-               if (IS_GEN6(dev) && IS_eDP(intel_encoder)) {
+               if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
                        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);
+                       signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
-               if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
+               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_encoder, reg,
+               if (!intel_dp_set_link_train(intel_dp, reg,
                                             DP_TRAINING_PATTERN_2, train_set,
                                             false))
                        break;
 
                udelay(400);
-               if (!intel_dp_get_link_status(intel_encoder, link_status))
+               if (!intel_dp_get_link_status(intel_dp, link_status))
                        break;
 
-               if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) {
+               if (intel_channel_eq_ok(link_status, intel_dp->lane_count)) {
                        channel_eq = true;
                        break;
                }
@@ -1250,53 +1229,53 @@ intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
                        break;
 
                /* Compute new train_set as requested by target */
-               intel_get_adjust_train(intel_encoder, link_status, dp_priv->lane_count, train_set);
+               intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
                ++tries;
        }
 
-       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
+       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp))
                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_encoder,
+       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);
 }
 
 static void
-intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP)
+intel_dp_link_down(struct intel_dp *intel_dp)
 {
-       struct drm_device *dev = intel_encoder->enc.dev;
+       struct drm_device *dev = intel_dp->base.enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
+       uint32_t DP = intel_dp->DP;
 
        DRM_DEBUG_KMS("\n");
 
-       if (IS_eDP(intel_encoder)) {
+       if (IS_eDP(intel_dp)) {
                DP &= ~DP_PLL_ENABLE;
-               I915_WRITE(dp_priv->output_reg, DP);
-               POSTING_READ(dp_priv->output_reg);
+               I915_WRITE(intel_dp->output_reg, DP);
+               POSTING_READ(intel_dp->output_reg);
                udelay(100);
        }
 
-       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) {
+       if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) {
                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);
+               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(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
-               POSTING_READ(dp_priv->output_reg);
+               I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
+               POSTING_READ(intel_dp->output_reg);
        }
 
        udelay(17000);
 
-       if (IS_eDP(intel_encoder))
+       if (IS_eDP(intel_dp))
                DP |= DP_LINK_TRAIN_OFF;
-       I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN);
-       POSTING_READ(dp_priv->output_reg);
+       I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
+       POSTING_READ(intel_dp->output_reg);
 }
 
 /*
@@ -1309,41 +1288,39 @@ intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP)
  */
 
 static void
-intel_dp_check_link_status(struct intel_encoder *intel_encoder)
+intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        uint8_t link_status[DP_LINK_STATUS_SIZE];
 
-       if (!intel_encoder->enc.crtc)
+       if (!intel_dp->base.enc.crtc)
                return;
 
-       if (!intel_dp_get_link_status(intel_encoder, link_status)) {
-               intel_dp_link_down(intel_encoder, dp_priv->DP);
+       if (!intel_dp_get_link_status(intel_dp, link_status)) {
+               intel_dp_link_down(intel_dp);
                return;
        }
 
-       if (!intel_channel_eq_ok(link_status, dp_priv->lane_count))
-               intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
+       if (!intel_channel_eq_ok(link_status, intel_dp->lane_count))
+               intel_dp_link_train(intel_dp);
 }
 
 static enum drm_connector_status
 ironlake_dp_detect(struct drm_connector *connector)
 {
        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;
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        enum drm_connector_status status;
 
        status = connector_status_disconnected;
-       if (intel_dp_aux_native_read(intel_encoder,
-                                    0x000, dp_priv->dpcd,
-                                    sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
+       if (intel_dp_aux_native_read(intel_dp,
+                                    0x000, intel_dp->dpcd,
+                                    sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
        {
-               if (dp_priv->dpcd[0] != 0)
+               if (intel_dp->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]);
+       DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],
+                     intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);
        return status;
 }
 
@@ -1357,19 +1334,18 @@ static enum drm_connector_status
 intel_dp_detect(struct drm_connector *connector)
 {
        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 intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct drm_device *dev = intel_dp->base.enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        uint32_t temp, bit;
        enum drm_connector_status status;
 
-       dp_priv->has_audio = false;
+       intel_dp->has_audio = false;
 
        if (HAS_PCH_SPLIT(dev))
                return ironlake_dp_detect(connector);
 
-       switch (dp_priv->output_reg) {
+       switch (intel_dp->output_reg) {
        case DP_B:
                bit = DPB_HOTPLUG_INT_STATUS;
                break;
@@ -1389,11 +1365,11 @@ intel_dp_detect(struct drm_connector *connector)
                return connector_status_disconnected;
 
        status = connector_status_disconnected;
-       if (intel_dp_aux_native_read(intel_encoder,
-                                    0x000, dp_priv->dpcd,
-                                    sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
+       if (intel_dp_aux_native_read(intel_dp,
+                                    0x000, intel_dp->dpcd,
+                                    sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
        {
-               if (dp_priv->dpcd[0] != 0)
+               if (intel_dp->dpcd[0] != 0)
                        status = connector_status_connected;
        }
        return status;
@@ -1402,18 +1378,17 @@ intel_dp_detect(struct drm_connector *connector)
 static int intel_dp_get_modes(struct drm_connector *connector)
 {
        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 intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct drm_device *dev = intel_dp->base.enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
        int ret;
 
        /* We should parse the EDID data and find out if it has an audio sink
         */
 
-       ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
+       ret = intel_ddc_get_modes(connector, intel_dp->base.ddc_bus);
        if (ret) {
-               if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
+               if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
                    !dev_priv->panel_fixed_mode) {
                        struct drm_display_mode *newmode;
                        list_for_each_entry(newmode, &connector->probed_modes,
@@ -1430,7 +1405,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_encoder) || IS_PCH_eDP(dp_priv)) {
+       if (IS_eDP(intel_dp) || IS_PCH_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,27 +1445,17 @@ static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs =
        .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 = {
-       .destroy = intel_dp_enc_destroy,
+       .destroy = intel_encoder_destroy,
 };
 
 void
 intel_dp_hot_plug(struct intel_encoder *intel_encoder)
 {
-       struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
+       struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
 
-       if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON)
-               intel_dp_check_link_status(intel_encoder);
+       if (intel_dp->dpms_mode == DRM_MODE_DPMS_ON)
+               intel_dp_check_link_status(intel_dp);
 }
 
 /* Return which DP Port should be selected for Transcoder DP control */
@@ -1500,18 +1465,18 @@ 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) {
+               struct intel_dp *intel_dp;
+
                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;
-               }
+               intel_dp = enc_to_intel_dp(encoder);
+               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
+                       return intel_dp->output_reg;
        }
+
        return -1;
 }
 
@@ -1540,30 +1505,28 @@ 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_dp *intel_dp;
        struct intel_encoder *intel_encoder;
        struct intel_connector *intel_connector;
-       struct intel_dp_priv *dp_priv;
        const char *name = NULL;
        int type;
 
-       intel_encoder = kcalloc(sizeof(struct intel_encoder) +
-                              sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
-       if (!intel_encoder)
+       intel_dp = kzalloc(sizeof(struct intel_dp), GFP_KERNEL);
+       if (!intel_dp)
                return;
 
        intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
        if (!intel_connector) {
-               kfree(intel_encoder);
+               kfree(intel_dp);
                return;
        }
+       intel_encoder = &intel_dp->base;
 
-       dp_priv = (struct intel_dp_priv *)(intel_encoder + 1);
-
-       if (HAS_PCH_SPLIT(dev) && (output_reg == PCH_DP_D))
+       if (HAS_PCH_SPLIT(dev) && output_reg == PCH_DP_D)
                if (intel_dpd_is_edp(dev))
-                       dp_priv->is_pch_edp = true;
+                       intel_dp->is_pch_edp = true;
 
-       if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
+       if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {
                type = DRM_MODE_CONNECTOR_eDP;
                intel_encoder->type = INTEL_OUTPUT_EDP;
        } else {
@@ -1584,18 +1547,16 @@ 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_encoder))
+       if (IS_eDP(intel_dp))
                intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
 
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
        connector->interlace_allowed = true;
        connector->doublescan_allowed = 0;
 
-       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_encoder->dev_priv = dp_priv;
+       intel_dp->output_reg = 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_MODE_ENCODER_TMDS);
@@ -1630,12 +1591,12 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                        break;
        }
 
-       intel_dp_i2c_init(intel_encoder, intel_connector, name);
+       intel_dp_i2c_init(intel_dp, intel_connector, name);
 
-       intel_encoder->ddc_bus = &dp_priv->adapter;
+       intel_encoder->ddc_bus = &intel_dp->adapter;
        intel_encoder->hot_plug = intel_dp_hot_plug;
 
-       if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
+       if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {
                /* initialize panel mode from VBT if available for eDP */
                if (dev_priv->lfp_lvds_vbt_mode) {
                        dev_priv->panel_fixed_mode =