diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 92 |
1 files changed, 69 insertions, 23 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ee3942f0b068..fdff1d420c14 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1631,6 +1631,10 @@ static void intel_dp_get_config(struct intel_encoder *encoder, | |||
1631 | 1631 | ||
1632 | pipe_config->adjusted_mode.flags |= flags; | 1632 | pipe_config->adjusted_mode.flags |= flags; |
1633 | 1633 | ||
1634 | if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && | ||
1635 | tmp & DP_COLOR_RANGE_16_235) | ||
1636 | pipe_config->limited_color_range = true; | ||
1637 | |||
1634 | pipe_config->has_dp_encoder = true; | 1638 | pipe_config->has_dp_encoder = true; |
1635 | 1639 | ||
1636 | intel_dp_get_m_n(crtc, pipe_config); | 1640 | intel_dp_get_m_n(crtc, pipe_config); |
@@ -3553,6 +3557,9 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) | |||
3553 | if (WARN_ON(!intel_encoder->base.crtc)) | 3557 | if (WARN_ON(!intel_encoder->base.crtc)) |
3554 | return; | 3558 | return; |
3555 | 3559 | ||
3560 | if (!to_intel_crtc(intel_encoder->base.crtc)->active) | ||
3561 | return; | ||
3562 | |||
3556 | /* Try to read receiver status if the link appears to be up */ | 3563 | /* Try to read receiver status if the link appears to be up */ |
3557 | if (!intel_dp_get_link_status(intel_dp, link_status)) { | 3564 | if (!intel_dp_get_link_status(intel_dp, link_status)) { |
3558 | return; | 3565 | return; |
@@ -3658,24 +3665,12 @@ ironlake_dp_detect(struct intel_dp *intel_dp) | |||
3658 | return intel_dp_detect_dpcd(intel_dp); | 3665 | return intel_dp_detect_dpcd(intel_dp); |
3659 | } | 3666 | } |
3660 | 3667 | ||
3661 | static enum drm_connector_status | 3668 | static int g4x_digital_port_connected(struct drm_device *dev, |
3662 | g4x_dp_detect(struct intel_dp *intel_dp) | 3669 | struct intel_digital_port *intel_dig_port) |
3663 | { | 3670 | { |
3664 | struct drm_device *dev = intel_dp_to_dev(intel_dp); | ||
3665 | struct drm_i915_private *dev_priv = dev->dev_private; | 3671 | struct drm_i915_private *dev_priv = dev->dev_private; |
3666 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||
3667 | uint32_t bit; | 3672 | uint32_t bit; |
3668 | 3673 | ||
3669 | /* Can't disconnect eDP, but you can close the lid... */ | ||
3670 | if (is_edp(intel_dp)) { | ||
3671 | enum drm_connector_status status; | ||
3672 | |||
3673 | status = intel_panel_detect(dev); | ||
3674 | if (status == connector_status_unknown) | ||
3675 | status = connector_status_connected; | ||
3676 | return status; | ||
3677 | } | ||
3678 | |||
3679 | if (IS_VALLEYVIEW(dev)) { | 3674 | if (IS_VALLEYVIEW(dev)) { |
3680 | switch (intel_dig_port->port) { | 3675 | switch (intel_dig_port->port) { |
3681 | case PORT_B: | 3676 | case PORT_B: |
@@ -3688,7 +3683,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) | |||
3688 | bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; | 3683 | bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; |
3689 | break; | 3684 | break; |
3690 | default: | 3685 | default: |
3691 | return connector_status_unknown; | 3686 | return -EINVAL; |
3692 | } | 3687 | } |
3693 | } else { | 3688 | } else { |
3694 | switch (intel_dig_port->port) { | 3689 | switch (intel_dig_port->port) { |
@@ -3702,11 +3697,36 @@ g4x_dp_detect(struct intel_dp *intel_dp) | |||
3702 | bit = PORTD_HOTPLUG_LIVE_STATUS_G4X; | 3697 | bit = PORTD_HOTPLUG_LIVE_STATUS_G4X; |
3703 | break; | 3698 | break; |
3704 | default: | 3699 | default: |
3705 | return connector_status_unknown; | 3700 | return -EINVAL; |
3706 | } | 3701 | } |
3707 | } | 3702 | } |
3708 | 3703 | ||
3709 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0) | 3704 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0) |
3705 | return 0; | ||
3706 | return 1; | ||
3707 | } | ||
3708 | |||
3709 | static enum drm_connector_status | ||
3710 | g4x_dp_detect(struct intel_dp *intel_dp) | ||
3711 | { | ||
3712 | struct drm_device *dev = intel_dp_to_dev(intel_dp); | ||
3713 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||
3714 | int ret; | ||
3715 | |||
3716 | /* Can't disconnect eDP, but you can close the lid... */ | ||
3717 | if (is_edp(intel_dp)) { | ||
3718 | enum drm_connector_status status; | ||
3719 | |||
3720 | status = intel_panel_detect(dev); | ||
3721 | if (status == connector_status_unknown) | ||
3722 | status = connector_status_connected; | ||
3723 | return status; | ||
3724 | } | ||
3725 | |||
3726 | ret = g4x_digital_port_connected(dev, intel_dig_port); | ||
3727 | if (ret == -EINVAL) | ||
3728 | return connector_status_unknown; | ||
3729 | else if (ret == 0) | ||
3710 | return connector_status_disconnected; | 3730 | return connector_status_disconnected; |
3711 | 3731 | ||
3712 | return intel_dp_detect_dpcd(intel_dp); | 3732 | return intel_dp_detect_dpcd(intel_dp); |
@@ -4003,6 +4023,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) | |||
4003 | kfree(intel_dig_port); | 4023 | kfree(intel_dig_port); |
4004 | } | 4024 | } |
4005 | 4025 | ||
4026 | static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) | ||
4027 | { | ||
4028 | struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); | ||
4029 | |||
4030 | if (!is_edp(intel_dp)) | ||
4031 | return; | ||
4032 | |||
4033 | edp_panel_vdd_off_sync(intel_dp); | ||
4034 | } | ||
4035 | |||
4006 | static void intel_dp_encoder_reset(struct drm_encoder *encoder) | 4036 | static void intel_dp_encoder_reset(struct drm_encoder *encoder) |
4007 | { | 4037 | { |
4008 | intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); | 4038 | intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); |
@@ -4037,18 +4067,30 @@ bool | |||
4037 | intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) | 4067 | intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) |
4038 | { | 4068 | { |
4039 | struct intel_dp *intel_dp = &intel_dig_port->dp; | 4069 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
4070 | struct intel_encoder *intel_encoder = &intel_dig_port->base; | ||
4040 | struct drm_device *dev = intel_dig_port->base.base.dev; | 4071 | struct drm_device *dev = intel_dig_port->base.base.dev; |
4041 | struct drm_i915_private *dev_priv = dev->dev_private; | 4072 | struct drm_i915_private *dev_priv = dev->dev_private; |
4042 | int ret; | 4073 | enum intel_display_power_domain power_domain; |
4074 | bool ret = true; | ||
4075 | |||
4043 | if (intel_dig_port->base.type != INTEL_OUTPUT_EDP) | 4076 | if (intel_dig_port->base.type != INTEL_OUTPUT_EDP) |
4044 | intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT; | 4077 | intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT; |
4045 | 4078 | ||
4046 | DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port, | 4079 | DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port, |
4047 | long_hpd ? "long" : "short"); | 4080 | long_hpd ? "long" : "short"); |
4048 | 4081 | ||
4082 | power_domain = intel_display_port_power_domain(intel_encoder); | ||
4083 | intel_display_power_get(dev_priv, power_domain); | ||
4084 | |||
4049 | if (long_hpd) { | 4085 | if (long_hpd) { |
4050 | if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) | 4086 | |
4051 | goto mst_fail; | 4087 | if (HAS_PCH_SPLIT(dev)) { |
4088 | if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) | ||
4089 | goto mst_fail; | ||
4090 | } else { | ||
4091 | if (g4x_digital_port_connected(dev, intel_dig_port) != 1) | ||
4092 | goto mst_fail; | ||
4093 | } | ||
4052 | 4094 | ||
4053 | if (!intel_dp_get_dpcd(intel_dp)) { | 4095 | if (!intel_dp_get_dpcd(intel_dp)) { |
4054 | goto mst_fail; | 4096 | goto mst_fail; |
@@ -4061,8 +4103,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) | |||
4061 | 4103 | ||
4062 | } else { | 4104 | } else { |
4063 | if (intel_dp->is_mst) { | 4105 | if (intel_dp->is_mst) { |
4064 | ret = intel_dp_check_mst_status(intel_dp); | 4106 | if (intel_dp_check_mst_status(intel_dp) == -EINVAL) |
4065 | if (ret == -EINVAL) | ||
4066 | goto mst_fail; | 4107 | goto mst_fail; |
4067 | } | 4108 | } |
4068 | 4109 | ||
@@ -4076,7 +4117,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) | |||
4076 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | 4117 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
4077 | } | 4118 | } |
4078 | } | 4119 | } |
4079 | return false; | 4120 | ret = false; |
4121 | goto put_power; | ||
4080 | mst_fail: | 4122 | mst_fail: |
4081 | /* if we were in MST mode, and device is not there get out of MST mode */ | 4123 | /* if we were in MST mode, and device is not there get out of MST mode */ |
4082 | if (intel_dp->is_mst) { | 4124 | if (intel_dp->is_mst) { |
@@ -4084,7 +4126,10 @@ mst_fail: | |||
4084 | intel_dp->is_mst = false; | 4126 | intel_dp->is_mst = false; |
4085 | drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); | 4127 | drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); |
4086 | } | 4128 | } |
4087 | return true; | 4129 | put_power: |
4130 | intel_display_power_put(dev_priv, power_domain); | ||
4131 | |||
4132 | return ret; | ||
4088 | } | 4133 | } |
4089 | 4134 | ||
4090 | /* Return which DP Port should be selected for Transcoder DP control */ | 4135 | /* Return which DP Port should be selected for Transcoder DP control */ |
@@ -4722,6 +4767,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) | |||
4722 | intel_encoder->disable = intel_disable_dp; | 4767 | intel_encoder->disable = intel_disable_dp; |
4723 | intel_encoder->get_hw_state = intel_dp_get_hw_state; | 4768 | intel_encoder->get_hw_state = intel_dp_get_hw_state; |
4724 | intel_encoder->get_config = intel_dp_get_config; | 4769 | intel_encoder->get_config = intel_dp_get_config; |
4770 | intel_encoder->suspend = intel_dp_encoder_suspend; | ||
4725 | if (IS_CHERRYVIEW(dev)) { | 4771 | if (IS_CHERRYVIEW(dev)) { |
4726 | intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; | 4772 | intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; |
4727 | intel_encoder->pre_enable = chv_pre_enable_dp; | 4773 | intel_encoder->pre_enable = chv_pre_enable_dp; |