Commit c7ad3810 authored by Jesse Barnes's avatar Jesse Barnes Committed by Keith Packard

drm/i915/dp: manage sink power state if possible

On sinks with a DPCD rev of 1.1 or greater, we can send sink power
management commands to address 0x600 per section 5.1.5 of the
DisplayPort 1.1a spec.
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: default avatarKeith Packard <keithp@keithp.com>
Signed-off-by: default avatarKeith Packard <keithp@keithp.com>
parent df0c237d
...@@ -942,11 +942,44 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder) ...@@ -942,11 +942,44 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder)
udelay(200); udelay(200);
} }
/* If the sink supports it, try to set the power state appropriately */
static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
{
int ret, i;
/* Should have a valid DPCD by this point */
if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
return;
if (mode != DRM_MODE_DPMS_ON) {
ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER,
DP_SET_POWER_D3);
if (ret != 1)
DRM_DEBUG_DRIVER("failed to write sink power state\n");
} else {
/*
* When turning on, we need to retry for 1ms to give the sink
* time to wake up.
*/
for (i = 0; i < 3; i++) {
ret = intel_dp_aux_native_write_1(intel_dp,
DP_SET_POWER,
DP_SET_POWER_D0);
if (ret == 1)
break;
msleep(1);
}
}
}
static void intel_dp_prepare(struct drm_encoder *encoder) static void intel_dp_prepare(struct drm_encoder *encoder)
{ {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
/* Wake up the sink first */
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
ironlake_edp_backlight_off(dev); ironlake_edp_backlight_off(dev);
ironlake_edp_panel_off(dev); ironlake_edp_panel_off(dev);
...@@ -990,6 +1023,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ...@@ -990,6 +1023,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
if (mode != DRM_MODE_DPMS_ON) { if (mode != DRM_MODE_DPMS_ON) {
if (is_edp(intel_dp)) if (is_edp(intel_dp))
ironlake_edp_backlight_off(dev); ironlake_edp_backlight_off(dev);
intel_dp_sink_dpms(intel_dp, mode);
intel_dp_link_down(intel_dp); intel_dp_link_down(intel_dp);
if (is_edp(intel_dp)) if (is_edp(intel_dp))
ironlake_edp_panel_off(dev); ironlake_edp_panel_off(dev);
...@@ -998,6 +1032,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ...@@ -998,6 +1032,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
} else { } else {
if (is_edp(intel_dp)) if (is_edp(intel_dp))
ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_panel_vdd_on(intel_dp);
intel_dp_sink_dpms(intel_dp, mode);
if (!(dp_reg & DP_PORT_EN)) { if (!(dp_reg & DP_PORT_EN)) {
intel_dp_start_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment