Blob Blame History Raw
From 7d1fede03c5880003a08ff080e6e41984902be46 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs@redhat.com>
Date: Fri, 19 May 2017 23:59:35 +1000
Subject: [PATCH] drm/nouveau/disp/g94-: port OR DP drive setting control to nvkm_ior
Git-commit: 7d1fede03c5880003a08ff080e6e41984902be46
Patch-mainline: v4.13-rc1
References: bsc#1095094

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c       |   24 +++++++-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h       |    2 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h      |    4 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h     |    2 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c   |   59 +++----------------
 drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c |   52 +++--------------
 drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c |    1 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c |    2 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c |   60 ++++----------------
 drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c |    1 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c |    1 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c |    1 
 12 files changed, 66 insertions(+), 143 deletions(-)

--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -73,9 +73,15 @@ static int
 nvkm_dp_train_drive(struct lt_state *lt, bool pc)
 {
 	struct nvkm_dp *dp = lt->dp;
+	struct nvkm_ior *ior = dp->outp.ior;
+	struct nvkm_bios *bios = ior->disp->engine.subdev.device->bios;
+	struct nvbios_dpout info;
+	struct nvbios_dpcfg ocfg;
+	u8  ver, hdr, cnt, len;
+	u32 data;
 	int ret, i;
 
-	for (i = 0; i < dp->outp.ior->dp.nr; i++) {
+	for (i = 0; i < ior->dp.nr; i++) {
 		u8 lane = (lt->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
 		u8 lpc2 = (lt->pc2stat >> (i * 2)) & 0x3;
 		u8 lpre = (lane & 0x0c) >> 2;
@@ -99,7 +105,21 @@ nvkm_dp_train_drive(struct lt_state *lt,
 
 		OUTP_TRACE(&dp->outp, "config lane %d %02x %02x",
 			   i, lt->conf[i], lpc2);
-		dp->func->drv_ctl(dp, i, lvsw & 3, lpre & 3, lpc2 & 3);
+
+		data = nvbios_dpout_match(bios, dp->outp.info.hasht,
+						dp->outp.info.hashm,
+					  &ver, &hdr, &cnt, &len, &info);
+		if (!data)
+			continue;
+
+		data = nvbios_dpcfg_match(bios, data, lpc2 & 3, lvsw & 3,
+					  lpre & 3, &ver, &hdr, &cnt, &len,
+					  &ocfg);
+		if (!data)
+			continue;
+
+		ior->func->dp.drive(ior, i, ocfg.pc, ocfg.dc,
+					    ocfg.pe, ocfg.tx_pu);
 	}
 
 	ret = nvkm_wraux(dp->aux, DPCD_LC03(0), lt->conf, 4);
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
@@ -33,7 +33,6 @@ struct nvkm_dp {
 #define nvkm_output_dp nvkm_dp
 
 struct nvkm_output_dp_func {
-	int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc);
 	void (*vcpi)(struct nvkm_output_dp *, int head, u8 start_slot,
 		     u8 num_slots, u16 pbn, u16 aligned_pbn);
 };
@@ -51,7 +50,6 @@ int g94_sor_dp_new(struct nvkm_disp *, i
 
 int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
 		     struct nvkm_output **);
-int gf119_sor_dp_drv_ctl(struct nvkm_dp *, int, int, int, int);
 void gf119_sor_dp_vcpi(struct nvkm_dp *, int, u8, u8, u16, u16);
 
 int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -56,6 +56,8 @@ struct nvkm_ior_func {
 		int (*links)(struct nvkm_ior *, struct nvkm_i2c_aux *);
 		void (*power)(struct nvkm_ior *, int nr);
 		void (*pattern)(struct nvkm_ior *, int pattern);
+		void (*drive)(struct nvkm_ior *, int ln, int pc,
+			      int dc, int pe, int tx_pu);
 	} dp;
 };
 
@@ -86,10 +88,12 @@ void g94_sor_state(struct nvkm_ior *, st
 int g94_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *);
 void g94_sor_dp_power(struct nvkm_ior *, int);
 void g94_sor_dp_pattern(struct nvkm_ior *, int);
+void g94_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int);
 
 void gf119_sor_state(struct nvkm_ior *, struct nvkm_ior_state *);
 int gf119_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *);
 void gf119_sor_dp_pattern(struct nvkm_ior *, int);
+void gf119_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int);
 
 void gm107_sor_dp_pattern(struct nvkm_ior *, int);
 
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
@@ -47,8 +47,6 @@ int nv50_sor_output_new(struct nvkm_disp
 int nv50_pior_output_new(struct nvkm_disp *, int, struct dcb_output *,
 			 struct nvkm_output **);
 
-u32 g94_sor_dp_lane_map(struct nvkm_device *, u8 lane);
-
 void gm200_sor_magic(struct nvkm_output *outp);
 
 #define OUTP_MSG(o,l,f,a...) do {                                              \
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
@@ -26,59 +26,22 @@
 
 #include <subdev/timer.h>
 
-static inline u32
-g94_sor_soff(struct nvkm_output_dp *outp)
-{
-	return (ffs(outp->base.info.or) - 1) * 0x800;
-}
-
-static inline u32
-g94_sor_loff(struct nvkm_output_dp *outp)
-{
-	return g94_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;
-}
-
-/*******************************************************************************
- * DisplayPort
- ******************************************************************************/
-u32
-g94_sor_dp_lane_map(struct nvkm_device *device, u8 lane)
-{
-	return nvkm_ior_find(device->disp, SOR, -1)->func->dp.lanes[lane] * 8;
-}
-
-static int
-g94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
+void
+g94_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
 {
-	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-	struct nvkm_bios *bios = device->bios;
-	const u32 shift = g94_sor_dp_lane_map(device, ln);
-	const u32 loff = g94_sor_loff(outp);
-	u32 addr, data[3];
-	u8  ver, hdr, cnt, len;
-	struct nvbios_dpout info;
-	struct nvbios_dpcfg ocfg;
-
-	addr = nvbios_dpout_match(bios, outp->base.info.hasht,
-					outp->base.info.hashm,
-				  &ver, &hdr, &cnt, &len, &info);
-	if (!addr)
-		return -ENODEV;
-
-	addr = nvbios_dpcfg_match(bios, addr, 0, vs, pe,
-				  &ver, &hdr, &cnt, &len, &ocfg);
-	if (!addr)
-		return -EINVAL;
+	struct nvkm_device *device = sor->disp->engine.subdev.device;
+	const u32  loff = nv50_sor_link(sor);
+	const u32 shift = sor->func->dp.lanes[ln] * 8;
+	u32 data[3];
 
 	data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift);
 	data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift);
 	data[2] = nvkm_rd32(device, 0x61c130 + loff);
-	if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0)
-		data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8);
-	nvkm_wr32(device, 0x61c118 + loff, data[0] | (ocfg.dc << shift));
-	nvkm_wr32(device, 0x61c120 + loff, data[1] | (ocfg.pe << shift));
+	if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0)
+		data[2] = (data[2] & ~0x0000ff00) | (pu << 8);
+	nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift));
+	nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift));
 	nvkm_wr32(device, 0x61c130 + loff, data[2]);
-	return 0;
 }
 
 void
@@ -130,7 +93,6 @@ g94_sor_dp_links(struct nvkm_ior *sor, s
 
 static const struct nvkm_output_dp_func
 g94_sor_dp_func = {
-	.drv_ctl = g94_sor_dp_drv_ctl,
 };
 
 int
@@ -298,6 +260,7 @@ g94_sor = {
 		.links = g94_sor_dp_links,
 		.power = g94_sor_dp_power,
 		.pattern = g94_sor_dp_pattern,
+		.drive = g94_sor_dp_drive,
 	},
 };
 
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
@@ -35,53 +35,24 @@ gf119_sor_dp_vcpi(struct nvkm_output_dp
 	nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn);
 }
 
-static inline u32
-gf119_sor_soff(struct nvkm_output_dp *outp)
-{
-	return (ffs(outp->base.info.or) - 1) * 0x800;
-}
-
-static inline u32
-gf119_sor_loff(struct nvkm_output_dp *outp)
-{
-	return gf119_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;
-}
-
-int
-gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
-		     int ln, int vs, int pe, int pc)
+void
+gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
 {
-	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-	struct nvkm_bios *bios = device->bios;
-	const u32 shift = g94_sor_dp_lane_map(device, ln);
-	const u32 loff = gf119_sor_loff(outp);
-	u32 addr, data[4];
-	u8  ver, hdr, cnt, len;
-	struct nvbios_dpout info;
-	struct nvbios_dpcfg ocfg;
-
-	addr = nvbios_dpout_match(bios, outp->base.info.hasht,
-					outp->base.info.hashm,
-				  &ver, &hdr, &cnt, &len, &info);
-	if (!addr)
-		return -ENODEV;
-
-	addr = nvbios_dpcfg_match(bios, addr, pc, vs, pe,
-				  &ver, &hdr, &cnt, &len, &ocfg);
-	if (!addr)
-		return -EINVAL;
+	struct nvkm_device *device = sor->disp->engine.subdev.device;
+	const u32  loff = nv50_sor_link(sor);
+	const u32 shift = sor->func->dp.lanes[ln] * 8;
+	u32 data[4];
 
 	data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift);
 	data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift);
 	data[2] = nvkm_rd32(device, 0x61c130 + loff);
-	if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0)
-		data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8);
-	nvkm_wr32(device, 0x61c118 + loff, data[0] | (ocfg.dc << shift));
-	nvkm_wr32(device, 0x61c120 + loff, data[1] | (ocfg.pe << shift));
+	if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0)
+		data[2] = (data[2] & ~0x0000ff00) | (pu << 8);
+	nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift));
+	nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift));
 	nvkm_wr32(device, 0x61c130 + loff, data[2]);
 	data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift);
-	nvkm_wr32(device, 0x61c13c + loff, data[3] | (ocfg.pc << shift));
-	return 0;
+	nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift));
 }
 
 void
@@ -115,7 +86,6 @@ gf119_sor_dp_links(struct nvkm_ior *sor,
 
 static const struct nvkm_output_dp_func
 gf119_sor_dp_func = {
-	.drv_ctl = gf119_sor_dp_drv_ctl,
 	.vcpi = gf119_sor_dp_vcpi,
 };
 
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c
@@ -33,6 +33,7 @@ gk104_sor = {
 		.links = gf119_sor_dp_links,
 		.power = g94_sor_dp_power,
 		.pattern = gf119_sor_dp_pattern,
+		.drive = gf119_sor_dp_drive,
 	},
 };
 
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
@@ -38,7 +38,6 @@ gm107_sor_dp_pattern(struct nvkm_ior *so
 
 static const struct nvkm_output_dp_func
 gm107_sor_dp_func = {
-	.drv_ctl = gf119_sor_dp_drv_ctl,
 	.vcpi = gf119_sor_dp_vcpi,
 };
 
@@ -61,6 +60,7 @@ gm107_sor = {
 		.links = gf119_sor_dp_links,
 		.power = g94_sor_dp_power,
 		.pattern = gm107_sor_dp_pattern,
+		.drive = gf119_sor_dp_drive,
 	},
 };
 
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
@@ -24,65 +24,30 @@
 #include "ior.h"
 #include "nv50.h"
 
-static inline u32
-gm200_sor_soff(struct nvkm_output_dp *outp)
+static void
+gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
 {
-	return (ffs(outp->base.info.or) - 1) * 0x800;
-}
-
-static inline u32
-gm200_sor_loff(struct nvkm_output_dp *outp)
-{
-	return gm200_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;
-}
+	struct nvkm_device *device = sor->disp->engine.subdev.device;
+	const u32  loff = nv50_sor_link(sor);
+	const u32 shift = sor->func->dp.lanes[ln] * 8;
+	u32 data[4];
 
-static inline u32
-gm200_sor_dp_lane_map(struct nvkm_device *device, u8 lane)
-{
-	return nvkm_ior_find(device->disp, SOR, -1)->func->dp.lanes[lane] * 8;
-}
-
-static int
-gm200_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
-		     int ln, int vs, int pe, int pc)
-{
-	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-	struct nvkm_bios *bios = device->bios;
-	const u32 shift = gm200_sor_dp_lane_map(device, ln);
-	const u32 loff = gm200_sor_loff(outp);
-	u32 addr, data[4];
-	u8  ver, hdr, cnt, len;
-	struct nvbios_dpout info;
-	struct nvbios_dpcfg ocfg;
-
-	addr = nvbios_dpout_match(bios, outp->base.info.hasht,
-					outp->base.info.hashm,
-				  &ver, &hdr, &cnt, &len, &info);
-	if (!addr)
-		return -ENODEV;
-
-	addr = nvbios_dpcfg_match(bios, addr, pc, vs, pe,
-				  &ver, &hdr, &cnt, &len, &ocfg);
-	if (!addr)
-		return -EINVAL;
-	ocfg.tx_pu &= 0x0f;
+	pu &= 0x0f;
 
 	data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift);
 	data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift);
 	data[2] = nvkm_rd32(device, 0x61c130 + loff);
-	if ((data[2] & 0x00000f00) < (ocfg.tx_pu << 8) || ln == 0)
-		data[2] = (data[2] & ~0x00000f00) | (ocfg.tx_pu << 8);
-	nvkm_wr32(device, 0x61c118 + loff, data[0] | (ocfg.dc << shift));
-	nvkm_wr32(device, 0x61c120 + loff, data[1] | (ocfg.pe << shift));
+	if ((data[2] & 0x00000f00) < (pu << 8) || ln == 0)
+		data[2] = (data[2] & ~0x00000f00) | (pu << 8);
+	nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift));
+	nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift));
 	nvkm_wr32(device, 0x61c130 + loff, data[2]);
 	data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift);
-	nvkm_wr32(device, 0x61c13c + loff, data[3] | (ocfg.pc << shift));
-	return 0;
+	nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift));
 }
 
 static const struct nvkm_output_dp_func
 gm200_sor_dp_func = {
-	.drv_ctl = gm200_sor_dp_drv_ctl,
 	.vcpi = gf119_sor_dp_vcpi,
 };
 
@@ -117,6 +82,7 @@ gm200_sor = {
 		.links = gf119_sor_dp_links,
 		.power = g94_sor_dp_power,
 		.pattern = gm107_sor_dp_pattern,
+		.drive = gm200_sor_dp_drive,
 	},
 };
 
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c
@@ -33,6 +33,7 @@ gt215_sor = {
 		.links = g94_sor_dp_links,
 		.power = g94_sor_dp_power,
 		.pattern = g94_sor_dp_pattern,
+		.drive = g94_sor_dp_drive,
 	},
 };
 
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c
@@ -33,6 +33,7 @@ mcp77_sor = {
 		.links = g94_sor_dp_links,
 		.power = g94_sor_dp_power,
 		.pattern = g94_sor_dp_pattern,
+		.drive = g94_sor_dp_drive,
 	},
 };
 
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c
@@ -33,6 +33,7 @@ mcp89_sor = {
 		.links = g94_sor_dp_links,
 		.power = g94_sor_dp_power,
 		.pattern = g94_sor_dp_pattern,
+		.drive = g94_sor_dp_drive,
 	},
 };