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: Jesse Barnes <jbarnes@virtuousgeek.org> Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
committed by
Keith Packard
parent
df0c237d12
commit
c7ad381078
@@ -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)
|
|||||||
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)
|
|||||||
} 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)) {
|
||||||
|
Reference in New Issue
Block a user