]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/gpu/drm/i915/intel_dp.c
drm/i915: wait for actual vblank, not just 20ms
[net-next-2.6.git] / drivers / gpu / drm / i915 / intel_dp.c
index d1b4ece4df0075de1736e2076cde4f47a2b583fb..9caccd03dccb6841fea4be4c5fa43f5e8822ee33 100644 (file)
@@ -831,6 +831,60 @@ static void ironlake_edp_backlight_off (struct drm_device *dev)
        I915_WRITE(PCH_PP_CONTROL, pp);
 }
 
+static void ironlake_edp_pll_on(struct drm_encoder *encoder)
+{
+       struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dpa_ctl;
+
+       DRM_DEBUG_KMS("\n");
+       dpa_ctl = I915_READ(DP_A);
+       dpa_ctl &= ~DP_PLL_ENABLE;
+       I915_WRITE(DP_A, dpa_ctl);
+}
+
+static void ironlake_edp_pll_off(struct drm_encoder *encoder)
+{
+       struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dpa_ctl;
+
+       dpa_ctl = I915_READ(DP_A);
+       dpa_ctl |= DP_PLL_ENABLE;
+       I915_WRITE(DP_A, dpa_ctl);
+       udelay(200);
+}
+
+static void intel_dp_prepare(struct drm_encoder *encoder)
+{
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dp_reg = I915_READ(intel_dp->output_reg);
+
+       if (IS_eDP(intel_dp)) {
+               ironlake_edp_backlight_off(dev);
+               ironlake_edp_panel_on(dev);
+               ironlake_edp_pll_on(encoder);
+       }
+       if (dp_reg & DP_PORT_EN)
+               intel_dp_link_down(intel_dp);
+}
+
+static void intel_dp_commit(struct drm_encoder *encoder)
+{
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dp_reg = I915_READ(intel_dp->output_reg);
+
+       if (!(dp_reg & DP_PORT_EN)) {
+               intel_dp_link_train(intel_dp);
+       }
+       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
+               ironlake_edp_backlight_on(dev);
+}
+
 static void
 intel_dp_dpms(struct drm_encoder *encoder, int mode)
 {
@@ -840,20 +894,21 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
        uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
        if (mode != DRM_MODE_DPMS_ON) {
-               if (dp_reg & DP_PORT_EN) {
-                       intel_dp_link_down(intel_dp);
-                       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
-                               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);
+               if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
+                       ironlake_edp_pll_off(encoder);
        } else {
                if (!(dp_reg & DP_PORT_EN)) {
-                       intel_dp_link_train(intel_dp);
-                       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
+                       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
                                ironlake_edp_panel_on(dev);
+                       intel_dp_link_train(intel_dp);
+                       if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
                                ironlake_edp_backlight_on(dev);
-                       }
                }
        }
        intel_dp->dpms_mode = mode;
@@ -1090,12 +1145,13 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 {
        struct drm_device *dev = intel_dp->base.enc.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
        int ret;
 
        I915_WRITE(intel_dp->output_reg, dp_reg_value);
        POSTING_READ(intel_dp->output_reg);
        if (first)
-               intel_wait_for_vblank(dev);
+               intel_wait_for_vblank(dev, intel_crtc->pipe);
 
        intel_dp_aux_native_write_1(intel_dp,
                                    DP_TRAINING_PATTERN_SET,
@@ -1428,9 +1484,9 @@ intel_dp_destroy (struct drm_connector *connector)
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
        .dpms = intel_dp_dpms,
        .mode_fixup = intel_dp_mode_fixup,
-       .prepare = intel_encoder_prepare,
+       .prepare = intel_dp_prepare,
        .mode_set = intel_dp_mode_set,
-       .commit = intel_encoder_commit,
+       .commit = intel_dp_commit,
 };
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {