From d9c9134f5968f2a882395305e1f55648de63d328 Mon Sep 17 00:00:00 2001
From: Damien Diederen
Date: Sat, 22 Mar 2014 17:59:55 +0100
Subject: [PATCH] [RFC] drm/nv50: (Partially) re-enable DPMS over DP
Commit 0a0afd28 (drm/nv50-/disp: move DP link training to core and
train from supervisor) removed a call to 'nouveau_dp_dpms' at the
bottom of nv50_display.c.
Without this call, 'xset dpms force {on,off}' does not have any effect
on my DP-attached monitor.
This proof-of-concept patch re-adds the call, as well as a partial
version of nouveau_dp_dpms which causes 'force off' to work again.
It is not clear to me how to trigger link training in the supervisor,
so nouveau_dp_dpms skips that step when handling DRM_MODE_DPMS_ON.
The result is that 'force on' does not cause the monitor to wake up,
and the connection is effectively dead.
Could somebody familiar with the driver could comment on the next
steps to undertake to restore the full {on,off} functionality?
---
drivers/gpu/drm/nouveau/nouveau_dp.c | 26 ++++++++++++++++++++++++++
drivers/gpu/drm/nouveau/nv50_display.c | 3 +++
2 files changed, 29 insertions(+)
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 36fd225..4c8c554 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -94,3 +94,29 @@ nouveau_dp_detect(struct drm_encoder *encoder)
return true;
}
+
+void
+nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
+ struct nouveau_object *core)
+{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nouveau_i2c_port *auxch;
+ u8 status;
+
+ auxch = nv_encoder->i2c;
+ if (!auxch)
+ return;
+
+ if (mode == DRM_MODE_DPMS_ON)
+ status = DP_SET_POWER_D0;
+ else
+ status = DP_SET_POWER_D3;
+
+ nv_wraux(auxch, DP_SET_POWER, &status, 1);
+
+ /* FIXME */
+ /*
+ if (mode == DRM_MODE_DPMS_ON)
+ nouveau_dp_train(...);
+ */
+}
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 2dccafc..0c6ceb1 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1740,6 +1740,9 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
}
nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON));
+
+ if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
+ nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, disp->core);
}
static bool
--
1.9.1