X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fi915%2Fintel_dp.c;h=11eb697dec0114f50b8c29e51e149f220be6b674;hb=95d5bfb3ac4cf5d7311f496761506c676f6b6323;hp=1a429cf55291a21257366b1b963bb4cbfbb9a8bb;hpb=16c255335b0ec39b4e5e976f4b260978aeed5a68;p=deliverable%2Flinux.git diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1a429cf55291..11eb697dec01 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1324,22 +1324,44 @@ static void intel_dp_get_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; u32 tmp, flags = 0; + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum port port = dp_to_dig_port(intel_dp)->port; + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - tmp = I915_READ(intel_dp->output_reg); + if ((port == PORT_A) || !HAS_PCH_CPT(dev)) { + tmp = I915_READ(intel_dp->output_reg); + if (tmp & DP_SYNC_HS_HIGH) + flags |= DRM_MODE_FLAG_PHSYNC; + else + flags |= DRM_MODE_FLAG_NHSYNC; - if (tmp & DP_SYNC_HS_HIGH) - flags |= DRM_MODE_FLAG_PHSYNC; - else - flags |= DRM_MODE_FLAG_NHSYNC; + if (tmp & DP_SYNC_VS_HIGH) + flags |= DRM_MODE_FLAG_PVSYNC; + else + flags |= DRM_MODE_FLAG_NVSYNC; + } else { + tmp = I915_READ(TRANS_DP_CTL(crtc->pipe)); + if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH) + flags |= DRM_MODE_FLAG_PHSYNC; + else + flags |= DRM_MODE_FLAG_NHSYNC; - if (tmp & DP_SYNC_VS_HIGH) - flags |= DRM_MODE_FLAG_PVSYNC; - else - flags |= DRM_MODE_FLAG_NVSYNC; + if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH) + flags |= DRM_MODE_FLAG_PVSYNC; + else + flags |= DRM_MODE_FLAG_NVSYNC; + } pipe_config->adjusted_mode.flags |= flags; + + if (dp_to_dig_port(intel_dp)->port == PORT_A) { + if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_160MHZ) + pipe_config->port_clock = 162000; + else + pipe_config->port_clock = 270000; + } } static void intel_disable_dp(struct intel_encoder *encoder) @@ -2681,7 +2703,7 @@ done: } static void -intel_dp_destroy(struct drm_connector *connector) +intel_dp_connector_destroy(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); @@ -2724,7 +2746,7 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = { .detect = intel_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = intel_dp_set_property, - .destroy = intel_dp_destroy, + .destroy = intel_dp_connector_destroy, }; static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { @@ -2986,8 +3008,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } else { /* if this fails, presume the device is a ghost */ DRM_INFO("failed to retrieve link info, disabling eDP\n"); - intel_dp_encoder_destroy(&intel_dig_port->base.base); - intel_dp_destroy(connector); return false; } @@ -3046,7 +3066,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct drm_i915_private *dev_priv = dev->dev_private; enum port port = intel_dig_port->port; const char *name = NULL; - int type; + int type, error; /* Preserve the current hw state. */ intel_dp->DP = I915_READ(intel_dp->output_reg); @@ -3144,10 +3164,22 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, BUG(); } - intel_dp_i2c_init(intel_dp, intel_connector, name); + error = intel_dp_i2c_init(intel_dp, intel_connector, name); + WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n", + error, port_name(port)); - if (!intel_edp_init_connector(intel_dp, intel_connector)) + if (!intel_edp_init_connector(intel_dp, intel_connector)) { + i2c_del_adapter(&intel_dp->adapter); + if (is_edp(intel_dp)) { + cancel_delayed_work_sync(&intel_dp->panel_vdd_work); + mutex_lock(&dev->mode_config.mutex); + ironlake_panel_vdd_off_sync(intel_dp); + mutex_unlock(&dev->mode_config.mutex); + } + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); return false; + } intel_dp_add_properties(intel_dp, connector); @@ -3206,5 +3238,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) intel_encoder->cloneable = false; intel_encoder->hot_plug = intel_dp_hot_plug; - intel_dp_init_connector(intel_dig_port, intel_connector); + if (!intel_dp_init_connector(intel_dig_port, intel_connector)) { + drm_encoder_cleanup(encoder); + kfree(intel_dig_port); + kfree(intel_connector); + } }