}
}
+static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 pp;
+
+ /*
+ * If the panel wasn't on, make sure there's not a currently
+ * active PP sequence before enabling AUX VDD.
+ */
+ if (!(I915_READ(PCH_PP_STATUS) & PP_ON))
+ msleep(dev_priv->panel_t3);
+
+ pp = I915_READ(PCH_PP_CONTROL);
+ pp |= EDP_FORCE_VDD;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+}
+
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 pp;
+
+ pp = I915_READ(PCH_PP_CONTROL);
+ pp &= ~EDP_FORCE_VDD;
+ I915_WRITE(PCH_PP_CONTROL, pp);
+ POSTING_READ(PCH_PP_CONTROL);
+
+ /* Make sure sequencer is idle before allowing subsequent activity */
+ msleep(dev_priv->panel_t12);
+}
+
/* Returns true if the panel was already on when called */
static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
{
if (is_edp(intel_dp)) {
ironlake_edp_backlight_off(dev);
- ironlake_edp_panel_on(intel_dp);
+ ironlake_edp_panel_off(dev);
if (!is_pch_edp(intel_dp))
ironlake_edp_pll_on(encoder);
else
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev;
+ if (is_edp(intel_dp))
+ ironlake_edp_panel_vdd_on(intel_dp);
+
intel_dp_start_link_train(intel_dp);
- if (is_edp(intel_dp))
+ if (is_edp(intel_dp)) {
ironlake_edp_panel_on(intel_dp);
+ ironlake_edp_panel_vdd_off(intel_dp);
+ }
intel_dp_complete_link_train(intel_dp);
ironlake_edp_pll_off(encoder);
} else {
if (is_edp(intel_dp))
- ironlake_edp_panel_on(intel_dp);
+ ironlake_edp_panel_vdd_on(intel_dp);
if (!(dp_reg & DP_PORT_EN)) {
intel_dp_start_link_train(intel_dp);
+ if (is_edp(intel_dp)) {
+ ironlake_edp_panel_on(intel_dp);
+ ironlake_edp_panel_vdd_off(intel_dp);
+ }
intel_dp_complete_link_train(intel_dp);
}
if (is_edp(intel_dp))
/* Cache some DPCD data in the eDP case */
if (is_edp(intel_dp)) {
int ret;
- bool was_on;
+ u32 pp_on, pp_div;
+
+ pp_on = I915_READ(PCH_PP_ON_DELAYS);
+ pp_div = I915_READ(PCH_PP_DIVISOR);
- was_on = ironlake_edp_panel_on(intel_dp);
+ /* Get T3 & T12 values (note: VESA not bspec terminology) */
+ dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16;
+ dev_priv->panel_t3 /= 10; /* t3 in 100us units */
+ dev_priv->panel_t12 = pp_div & 0xf;
+ dev_priv->panel_t12 *= 100; /* t12 in 100ms units */
+
+ ironlake_edp_panel_vdd_on(intel_dp);
ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV,
intel_dp->dpcd,
sizeof(intel_dp->dpcd));
} else {
DRM_ERROR("failed to retrieve link info\n");
}
- if (!was_on)
- ironlake_edp_panel_off(dev);
+ ironlake_edp_panel_vdd_off(intel_dp);
}
intel_encoder->hot_plug = intel_dp_hot_plug;