From 1ecee1cda3a33029c32721b6f2c61bc3f371e3bd Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs@redhat.com>
Date: Mon, 26 May 2014 11:57:57 +1000
Subject: [PATCH] drm/nouveau/disp/dp: split link config/power into two steps

We want to be able to power down the lanes for DPMS off.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
---
 .../gpu/drm/nouveau/core/engine/disp/dport.c  |  2 ++
 .../gpu/drm/nouveau/core/engine/disp/nv50.h   |  1 +
 .../gpu/drm/nouveau/core/engine/disp/outpdp.h |  1 +
 .../drm/nouveau/core/engine/disp/piornv50.c   |  7 ++++++
 .../drm/nouveau/core/engine/disp/sornv94.c    | 22 ++++++++++++++-----
 .../drm/nouveau/core/engine/disp/sornvd0.c    |  8 ++-----
 6 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
index efccbabca18c..5d4b034804af 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
@@ -94,6 +94,8 @@ dp_set_link_config(struct dp_state *dp)
 		return ret;
 	}
 
+	impl->lnk_pwr(outp, dp->link_nr);
+
 	/* set desired link configuration on the sink */
 	sink[0] = dp->link_bw / 27000;
 	sink[1] = dp->link_nr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index 67ad3f1f829c..1a886472b6f5 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -203,6 +203,7 @@ extern struct nvkm_output_dp_impl nv50_pior_dp_impl;
 extern struct nouveau_oclass *nv50_disp_outp_sclass[];
 
 extern struct nvkm_output_dp_impl nv94_sor_dp_impl;
+int nv94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int);
 extern struct nouveau_oclass *nv94_disp_outp_sclass[];
 
 extern struct nvkm_output_dp_impl nvd0_sor_dp_impl;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
index ab328dcad041..4c32cf53417b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
@@ -49,6 +49,7 @@ int  _nvkm_output_dp_fini(struct nouveau_object *, bool);
 struct nvkm_output_dp_impl {
 	struct nvkm_output_impl base;
 	int (*pattern)(struct nvkm_output_dp *, int);
+	int (*lnk_pwr)(struct nvkm_output_dp *, int nr);
 	int (*lnk_ctl)(struct nvkm_output_dp *, int nr, int bw, bool ef);
 	int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc);
 };
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
index 491e4d83b921..fe0f256f11bf 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
@@ -79,6 +79,12 @@ nv50_pior_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 	return port ? 0 : -ENODEV;
 }
 
+static int
+nv50_pior_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
+{
+	return 0;
+}
+
 static int
 nv50_pior_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 {
@@ -127,6 +133,7 @@ nv50_pior_dp_impl = {
 		.fini = _nvkm_output_dp_fini,
 	},
 	.pattern = nv50_pior_dp_pattern,
+	.lnk_pwr = nv50_pior_dp_lnk_pwr,
 	.lnk_ctl = nv50_pior_dp_lnk_ctl,
 	.drv_ctl = nv50_pior_dp_drv_ctl,
 };
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
index 5ee9a12be446..95d8c53d347d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
@@ -29,6 +29,7 @@
 #include <subdev/bios/dcb.h>
 #include <subdev/bios/dp.h>
 #include <subdev/bios/init.h>
+#include <subdev/timer.h>
 
 #include "nv50.h"
 #include "outpdp.h"
@@ -64,6 +65,20 @@ nv94_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 	return 0;
 }
 
+int
+nv94_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
+{
+	struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);
+	const u32 loff = nv94_sor_loff(outp);
+	u32 mask = 0, i;
+
+	for (i = 0; i < nr; i++)
+		mask |= 1 << (nv94_sor_dp_lane_map(priv, i) >> 3);
+
+	nv_mask(priv, 0x61c130 + loff, 0x0000000f, mask);
+	return 0;
+}
+
 static int
 nv94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 {
@@ -72,8 +87,6 @@ nv94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 	const u32 loff = nv94_sor_loff(outp);
 	u32 dpctrl = 0x00000000;
 	u32 clksor = 0x00000000;
-	u32 lane = 0;
-	int i;
 
 	dpctrl |= ((1 << nr) - 1) << 16;
 	if (ef)
@@ -81,12 +94,8 @@ nv94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 	if (bw > 0x06)
 		clksor |= 0x00040000;
 
-	for (i = 0; i < nr; i++)
-		lane |= 1 << (nv94_sor_dp_lane_map(priv, i) >> 3);
-
 	nv_mask(priv, 0x614300 + soff, 0x000c0000, clksor);
 	nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl);
-	nv_mask(priv, 0x61c130 + loff, 0x0000000f, lane);
 	return 0;
 }
 
@@ -132,6 +141,7 @@ nv94_sor_dp_impl = {
 		.fini = _nvkm_output_dp_fini,
 	},
 	.pattern = nv94_sor_dp_pattern,
+	.lnk_pwr = nv94_sor_dp_lnk_pwr,
 	.lnk_ctl = nv94_sor_dp_lnk_ctl,
 	.drv_ctl = nv94_sor_dp_drv_ctl,
 };
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
index c3120a762070..07cc2d527564 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
@@ -29,6 +29,7 @@
 #include <subdev/bios/dcb.h>
 #include <subdev/bios/dp.h>
 #include <subdev/bios/init.h>
+#include <subdev/timer.h>
 
 #include "nv50.h"
 
@@ -68,20 +69,14 @@ nvd0_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
 	const u32 loff = nvd0_sor_loff(outp);
 	u32 dpctrl = 0x00000000;
 	u32 clksor = 0x00000000;
-	u32 lane = 0;
-	int i;
 
 	clksor |= bw << 18;
 	dpctrl |= ((1 << nr) - 1) << 16;
 	if (ef)
 		dpctrl |= 0x00004000;
 
-	for (i = 0; i < nr; i++)
-		lane |= 1 << (nvd0_sor_dp_lane_map(priv, i) >> 3);
-
 	nv_mask(priv, 0x612300 + soff, 0x007c0000, clksor);
 	nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl);
-	nv_mask(priv, 0x61c130 + loff, 0x0000000f, lane);
 	return 0;
 }
 
@@ -128,6 +123,7 @@ nvd0_sor_dp_impl = {
 		.fini = _nvkm_output_dp_fini,
 	},
 	.pattern = nvd0_sor_dp_pattern,
+	.lnk_pwr = nv94_sor_dp_lnk_pwr,
 	.lnk_ctl = nvd0_sor_dp_lnk_ctl,
 	.drv_ctl = nvd0_sor_dp_drv_ctl,
 };
-- 
GitLab