Blob Blame History Raw
From e1b5d4d10e3c342f33c0019e3c97ac220c1944b6 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs@redhat.com>
Date: Wed, 1 Jun 2022 20:46:29 +1000
Subject: drm/nouveau/disp: split sor dp funcs out to their own struct
Git-commit: 9a4514fbffda6083d9f7fba4882142686783cfe4
Patch-mainline: v6.0-rc1
References: jsc#PED-1166 jsc#PED-1168 jsc#PED-1170 jsc#PED-1218 jsc#PED-1220 jsc#PED-1222 jsc#PED-1223 jsc#PED-1225 jsc#PED-2849

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Acked-by: Patrik Jakobsson <pjakobsson@suse.de>
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c |  8 ++---
 .../gpu/drm/nouveau/nvkm/engine/disp/g94.c    | 27 +++++++++--------
 .../gpu/drm/nouveau/nvkm/engine/disp/ga102.c  | 25 +++++++++-------
 .../gpu/drm/nouveau/nvkm/engine/disp/gf119.c  | 29 ++++++++++---------
 .../gpu/drm/nouveau/nvkm/engine/disp/gk104.c  | 12 +-------
 .../gpu/drm/nouveau/nvkm/engine/disp/gm107.c  | 25 +++++++++-------
 .../gpu/drm/nouveau/nvkm/engine/disp/gm200.c  | 27 +++++++++--------
 .../gpu/drm/nouveau/nvkm/engine/disp/gp100.c  | 12 +-------
 .../gpu/drm/nouveau/nvkm/engine/disp/gt215.c  | 25 +++++++++-------
 .../gpu/drm/nouveau/nvkm/engine/disp/gv100.c  | 23 ++++++++-------
 .../gpu/drm/nouveau/nvkm/engine/disp/ior.h    |  8 +++--
 .../gpu/drm/nouveau/nvkm/engine/disp/mcp77.c  | 11 +------
 .../gpu/drm/nouveau/nvkm/engine/disp/mcp89.c  | 25 +++++++++-------
 .../gpu/drm/nouveau/nvkm/engine/disp/nv50.c   | 21 ++++++++------
 .../drm/nouveau/nvkm/engine/disp/rootnv50.c   |  8 ++---
 .../gpu/drm/nouveau/nvkm/engine/disp/tu102.c  | 25 +++++++++-------
 16 files changed, 157 insertions(+), 154 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
index abf2c80cecb4..c1b3206f27e6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -142,7 +142,7 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc)
 		if (!data)
 			continue;
 
-		ior->func->dp.drive(ior, i, ocfg.pc, ocfg.dc, ocfg.pe, ocfg.tx_pu);
+		ior->func->dp->drive(ior, i, ocfg.pc, ocfg.dc, ocfg.pe, ocfg.tx_pu);
 	}
 
 	if (lt->repeater)
@@ -171,7 +171,7 @@ nvkm_dp_train_pattern(struct lt_state *lt, u8 pattern)
 	u8 sink_tp;
 
 	OUTP_TRACE(outp, "training pattern %d", pattern);
-	outp->ior->func->dp.pattern(outp->ior, pattern);
+	outp->ior->func->dp->pattern(outp->ior, pattern);
 
 	if (lt->repeater)
 		addr = DPCD_LTTPR_PATTERN_SET(lt->repeater);
@@ -328,7 +328,7 @@ nvkm_dp_train_links(struct nvkm_outp *outp, int rate)
 		);
 	}
 
-	ret = ior->func->dp.links(ior, outp->dp.aux);
+	ret = ior->func->dp->links(ior, outp->dp.aux);
 	if (ret) {
 		if (ret < 0) {
 			OUTP_ERR(outp, "train failed with %d", ret);
@@ -337,7 +337,7 @@ nvkm_dp_train_links(struct nvkm_outp *outp, int rate)
 		return 0;
 	}
 
-	ior->func->dp.power(ior, ior->dp.nr);
+	ior->func->dp->power(ior, ior->dp.nr);
 
 	/* Select LTTPR non-transparent mode if we have a valid configuration,
 	 * use transparent mode otherwise.
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
index 92feface3624..d808f6e8887c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
@@ -65,7 +65,7 @@ g94_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
 {
 	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;
+	const u32 shift = sor->func->dp->lanes[ln] * 8;
 	u32 data[3];
 
 	data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift);
@@ -107,7 +107,7 @@ g94_sor_dp_power(struct nvkm_ior *sor, int nr)
 	u32 mask = 0, i;
 
 	for (i = 0; i < nr; i++)
-		mask |= 1 << sor->func->dp.lanes[i];
+		mask |= 1 << sor->func->dp->lanes[i];
 
 	nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask);
 	nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000);
@@ -137,6 +137,18 @@ g94_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
 	return 0;
 }
 
+const struct nvkm_ior_func_dp
+g94_sor_dp = {
+	.lanes = { 2, 1, 0, 3},
+	.links = g94_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = g94_sor_dp_pattern,
+	.drive = g94_sor_dp_drive,
+	.audio_sym = g94_sor_dp_audio_sym,
+	.activesym = g94_sor_dp_activesym,
+	.watermark = g94_sor_dp_watermark,
+};
+
 static bool
 g94_sor_war_needed(struct nvkm_ior *sor)
 {
@@ -283,16 +295,7 @@ g94_sor = {
 	.clock = nv50_sor_clock,
 	.war_2 = g94_sor_war_2,
 	.war_3 = g94_sor_war_3,
-	.dp = {
-		.lanes = { 2, 1, 0, 3},
-		.links = g94_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = g94_sor_dp_pattern,
-		.drive = g94_sor_dp_drive,
-		.audio_sym = g94_sor_dp_audio_sym,
-		.activesym = g94_sor_dp_activesym,
-		.watermark = g94_sor_dp_watermark,
-	},
+	.dp = &g94_sor_dp,
 };
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c
index 9d008f090efe..94a198407172 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c
@@ -68,6 +68,19 @@ ga102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
 	return 0;
 }
 
+static const struct nvkm_ior_func_dp
+ga102_sor_dp = {
+	.lanes = { 0, 1, 2, 3 },
+	.links = ga102_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = gm107_sor_dp_pattern,
+	.drive = gm200_sor_dp_drive,
+	.vcpi = tu102_sor_dp_vcpi,
+	.audio = gv100_sor_dp_audio,
+	.audio_sym = gv100_sor_dp_audio_sym,
+	.watermark = gv100_sor_dp_watermark,
+};
+
 static void
 ga102_sor_clock(struct nvkm_ior *sor)
 {
@@ -96,17 +109,7 @@ ga102_sor = {
 		.ctrl = gv100_sor_hdmi_ctrl,
 		.scdc = gm200_sor_hdmi_scdc,
 	},
-	.dp = {
-		.lanes = { 0, 1, 2, 3 },
-		.links = ga102_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = gm107_sor_dp_pattern,
-		.drive = gm200_sor_dp_drive,
-		.vcpi = tu102_sor_dp_vcpi,
-		.audio = gv100_sor_dp_audio,
-		.audio_sym = gv100_sor_dp_audio_sym,
-		.watermark = gv100_sor_dp_watermark,
-	},
+	.dp = &ga102_sor_dp,
 	.hda = {
 		.hpd = gf119_sor_hda_hpd,
 		.eld = gf119_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
index e6ebc72ed6db..44bf07d8e244 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -123,7 +123,7 @@ gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
 {
 	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;
+	const u32 shift = sor->func->dp->lanes[ln] * 8;
 	u32 data[4];
 
 	data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift);
@@ -140,7 +140,7 @@ gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
 	nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift));
 }
 
-void
+static void
 gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern)
 {
 	struct nvkm_device *device = sor->disp->engine.subdev.device;
@@ -181,6 +181,19 @@ gf119_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
 	return 0;
 }
 
+const struct nvkm_ior_func_dp
+gf119_sor_dp = {
+	.lanes = { 2, 1, 0, 3 },
+	.links = gf119_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = gf119_sor_dp_pattern,
+	.drive = gf119_sor_dp_drive,
+	.vcpi = gf119_sor_dp_vcpi,
+	.audio = gf119_sor_dp_audio,
+	.audio_sym = gf119_sor_dp_audio_sym,
+	.watermark = gf119_sor_dp_watermark,
+};
+
 static void
 gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
 		    u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
@@ -288,17 +301,7 @@ gf119_sor = {
 	.hdmi = {
 		.ctrl = gf119_sor_hdmi_ctrl,
 	},
-	.dp = {
-		.lanes = { 2, 1, 0, 3 },
-		.links = gf119_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = gf119_sor_dp_pattern,
-		.drive = gf119_sor_dp_drive,
-		.vcpi = gf119_sor_dp_vcpi,
-		.audio = gf119_sor_dp_audio,
-		.audio_sym = gf119_sor_dp_audio_sym,
-		.watermark = gf119_sor_dp_watermark,
-	},
+	.dp = &gf119_sor_dp,
 	.hda = {
 		.hpd = gf119_sor_hda_hpd,
 		.eld = gf119_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
index b562a4d8ad2f..b75c1a3abc1e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
@@ -95,17 +95,7 @@ gk104_sor = {
 	.hdmi = {
 		.ctrl = gk104_sor_hdmi_ctrl,
 	},
-	.dp = {
-		.lanes = { 2, 1, 0, 3 },
-		.links = gf119_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = gf119_sor_dp_pattern,
-		.drive = gf119_sor_dp_drive,
-		.vcpi = gf119_sor_dp_vcpi,
-		.audio = gf119_sor_dp_audio,
-		.audio_sym = gf119_sor_dp_audio_sym,
-		.watermark = gf119_sor_dp_watermark,
-	},
+	.dp = &gf119_sor_dp,
 	.hda = {
 		.hpd = gf119_sor_hda_hpd,
 		.eld = gf119_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
index 0b25999e0e25..c9bf319c01d1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
@@ -52,6 +52,19 @@ gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern)
 		nvkm_mask(device, 0x61c12c + soff, mask, data);
 }
 
+static const struct nvkm_ior_func_dp
+gm107_sor_dp = {
+	.lanes = { 0, 1, 2, 3 },
+	.links = gf119_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = gm107_sor_dp_pattern,
+	.drive = gf119_sor_dp_drive,
+	.vcpi = gf119_sor_dp_vcpi,
+	.audio = gf119_sor_dp_audio,
+	.audio_sym = gf119_sor_dp_audio_sym,
+	.watermark = gf119_sor_dp_watermark,
+};
+
 static const struct nvkm_ior_func
 gm107_sor = {
 	.state = gf119_sor_state,
@@ -60,17 +73,7 @@ gm107_sor = {
 	.hdmi = {
 		.ctrl = gk104_sor_hdmi_ctrl,
 	},
-	.dp = {
-		.lanes = { 0, 1, 2, 3 },
-		.links = gf119_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = gm107_sor_dp_pattern,
-		.drive = gf119_sor_dp_drive,
-		.vcpi = gf119_sor_dp_vcpi,
-		.audio = gf119_sor_dp_audio,
-		.audio_sym = gf119_sor_dp_audio_sym,
-		.watermark = gf119_sor_dp_watermark,
-	},
+	.dp = &gm107_sor_dp,
 	.hda = {
 		.hpd = gf119_sor_hda_hpd,
 		.eld = gf119_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
index 990f3782d0c3..7cc6e82205ce 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
@@ -35,7 +35,7 @@ gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
 {
 	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;
+	const u32 shift = sor->func->dp->lanes[ln] * 8;
 	u32 data[4];
 
 	pu &= 0x0f;
@@ -54,6 +54,19 @@ gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
 	nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift));
 }
 
+const struct nvkm_ior_func_dp
+gm200_sor_dp = {
+	.lanes = { 0, 1, 2, 3 },
+	.links = gf119_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = gm107_sor_dp_pattern,
+	.drive = gm200_sor_dp_drive,
+	.vcpi = gf119_sor_dp_vcpi,
+	.audio = gf119_sor_dp_audio,
+	.audio_sym = gf119_sor_dp_audio_sym,
+	.watermark = gf119_sor_dp_watermark,
+};
+
 void
 gm200_sor_hdmi_scdc(struct nvkm_ior *ior, u8 scdc)
 {
@@ -122,17 +135,7 @@ gm200_sor = {
 		.ctrl = gk104_sor_hdmi_ctrl,
 		.scdc = gm200_sor_hdmi_scdc,
 	},
-	.dp = {
-		.lanes = { 0, 1, 2, 3 },
-		.links = gf119_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = gm107_sor_dp_pattern,
-		.drive = gm200_sor_dp_drive,
-		.vcpi = gf119_sor_dp_vcpi,
-		.audio = gf119_sor_dp_audio,
-		.audio_sym = gf119_sor_dp_audio_sym,
-		.watermark = gf119_sor_dp_watermark,
-	},
+	.dp = &gm200_sor_dp,
 	.hda = {
 		.hpd = gf119_sor_hda_hpd,
 		.eld = gf119_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
index beec3c8187a2..56a99217b740 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
@@ -41,17 +41,7 @@ gp100_sor = {
 		.ctrl = gk104_sor_hdmi_ctrl,
 		.scdc = gm200_sor_hdmi_scdc,
 	},
-	.dp = {
-		.lanes = { 0, 1, 2, 3 },
-		.links = gf119_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = gm107_sor_dp_pattern,
-		.drive = gm200_sor_dp_drive,
-		.vcpi = gf119_sor_dp_vcpi,
-		.audio = gf119_sor_dp_audio,
-		.audio_sym = gf119_sor_dp_audio_sym,
-		.watermark = gf119_sor_dp_watermark,
-	},
+	.dp = &gm200_sor_dp,
 	.hda = {
 		.hpd = gf119_sor_hda_hpd,
 		.eld = gf119_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
index 72a4c28ccd18..e01c0533bdf5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
@@ -73,6 +73,19 @@ gt215_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable)
 	);
 }
 
+static const struct nvkm_ior_func_dp
+gt215_sor_dp = {
+	.lanes = { 2, 1, 0, 3 },
+	.links = g94_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = g94_sor_dp_pattern,
+	.drive = g94_sor_dp_drive,
+	.audio = gt215_sor_dp_audio,
+	.audio_sym = g94_sor_dp_audio_sym,
+	.activesym = g94_sor_dp_activesym,
+	.watermark = g94_sor_dp_watermark,
+};
+
 void
 gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
 		    u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
@@ -148,17 +161,7 @@ gt215_sor = {
 	.hdmi = {
 		.ctrl = gt215_sor_hdmi_ctrl,
 	},
-	.dp = {
-		.lanes = { 2, 1, 0, 3 },
-		.links = g94_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = g94_sor_dp_pattern,
-		.drive = g94_sor_dp_drive,
-		.audio = gt215_sor_dp_audio,
-		.audio_sym = g94_sor_dp_audio_sym,
-		.activesym = g94_sor_dp_activesym,
-		.watermark = g94_sor_dp_watermark,
-	},
+	.dp = &gt215_sor_dp,
 	.hda = {
 		.hpd = gt215_sor_hda_hpd,
 		.eld = gt215_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
index aac1cdbea160..81c01a1bf92e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
@@ -79,6 +79,18 @@ gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable)
 	);
 }
 
+static const struct nvkm_ior_func_dp
+gv100_sor_dp = {
+	.lanes = { 0, 1, 2, 3 },
+	.links = gf119_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = gm107_sor_dp_pattern,
+	.drive = gm200_sor_dp_drive,
+	.audio = gv100_sor_dp_audio,
+	.audio_sym = gv100_sor_dp_audio_sym,
+	.watermark = gv100_sor_dp_watermark,
+};
+
 void
 gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
 		    u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
@@ -177,16 +189,7 @@ gv100_sor = {
 		.ctrl = gv100_sor_hdmi_ctrl,
 		.scdc = gm200_sor_hdmi_scdc,
 	},
-	.dp = {
-		.lanes = { 0, 1, 2, 3 },
-		.links = gf119_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = gm107_sor_dp_pattern,
-		.drive = gm200_sor_dp_drive,
-		.audio = gv100_sor_dp_audio,
-		.audio_sym = gv100_sor_dp_audio_sym,
-		.watermark = gv100_sor_dp_watermark,
-	},
+	.dp = &gv100_sor_dp,
 	.hda = {
 		.hpd = gf119_sor_hda_hpd,
 		.eld = gf119_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
index d1e494e06c38..5b49f7bd2c46 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -70,7 +70,7 @@ struct nvkm_ior_func {
 		void (*scdc)(struct nvkm_ior *, u8 scdc);
 	} hdmi;
 
-	struct {
+	const struct nvkm_ior_func_dp {
 		u8 lanes[4];
 		int (*links)(struct nvkm_ior *, struct nvkm_i2c_aux *);
 		void (*power)(struct nvkm_ior *, int nr);
@@ -84,7 +84,7 @@ struct nvkm_ior_func {
 		void (*activesym)(struct nvkm_ior *, int head,
 				  u8 TU, u8 VTUa, u8 VTUf, u8 VTUi);
 		void (*watermark)(struct nvkm_ior *, int head, u8 watermark);
-	} dp;
+	} *dp;
 
 	struct {
 		void (*hpd)(struct nvkm_ior *, int head, bool present);
@@ -128,6 +128,7 @@ void g84_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8
 
 int g94_sor_cnt(struct nvkm_disp *, unsigned long *);
 void g94_sor_state(struct nvkm_ior *, struct nvkm_ior_state *);
+extern const struct nvkm_ior_func_dp g94_sor_dp;
 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);
@@ -144,8 +145,8 @@ void gt215_sor_hda_eld(struct nvkm_ior *, int, u8 *, u8);
 int gf119_sor_cnt(struct nvkm_disp *, unsigned long *);
 void gf119_sor_state(struct nvkm_ior *, struct nvkm_ior_state *);
 void gf119_sor_clock(struct nvkm_ior *);
+extern const struct nvkm_ior_func_dp gf119_sor_dp;
 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 gf119_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16);
 void gf119_sor_dp_audio(struct nvkm_ior *, int, bool);
@@ -163,6 +164,7 @@ void gm107_sor_dp_pattern(struct nvkm_ior *, int);
 void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *);
 int gm200_sor_route_get(struct nvkm_outp *, int *);
 void gm200_sor_hdmi_scdc(struct nvkm_ior *, u8);
+extern const struct nvkm_ior_func_dp gm200_sor_dp;
 void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int);
 
 int gp100_sor_new(struct nvkm_disp *, int);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c
index f0d23a66b782..915a0edc0c84 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c
@@ -34,16 +34,7 @@ mcp77_sor = {
 	.hdmi = {
 		.ctrl = g84_sor_hdmi_ctrl,
 	},
-	.dp = {
-		.lanes = { 2, 1, 0, 3},
-		.links = g94_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = g94_sor_dp_pattern,
-		.drive = g94_sor_dp_drive,
-		.audio_sym = g94_sor_dp_audio_sym,
-		.activesym = g94_sor_dp_activesym,
-		.watermark = g94_sor_dp_watermark,
-	},
+	.dp = &g94_sor_dp,
 };
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
index 25a1934f6882..ab359deb1520 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
@@ -26,6 +26,19 @@
 
 #include <nvif/class.h>
 
+static const struct nvkm_ior_func_dp
+mcp89_sor_dp = {
+	.lanes = { 3, 2, 1, 0 },
+	.links = g94_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = g94_sor_dp_pattern,
+	.drive = g94_sor_dp_drive,
+	.audio = gt215_sor_dp_audio,
+	.audio_sym = g94_sor_dp_audio_sym,
+	.activesym = g94_sor_dp_activesym,
+	.watermark = g94_sor_dp_watermark,
+};
+
 static const struct nvkm_ior_func
 mcp89_sor = {
 	.state = g94_sor_state,
@@ -34,17 +47,7 @@ mcp89_sor = {
 	.hdmi = {
 		.ctrl = gt215_sor_hdmi_ctrl,
 	},
-	.dp = {
-		.lanes = { 3, 2, 1, 0 },
-		.links = g94_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = g94_sor_dp_pattern,
-		.drive = g94_sor_dp_drive,
-		.audio = gt215_sor_dp_audio,
-		.audio_sym = g94_sor_dp_audio_sym,
-		.activesym = g94_sor_dp_activesym,
-		.watermark = g94_sor_dp_watermark,
-	},
+	.dp = &mcp89_sor_dp,
 	.hda = {
 		.hpd = gt215_sor_hda_hpd,
 		.eld = gt215_sor_hda_eld,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index a50239d2077f..25853cbc55f0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -66,6 +66,11 @@ nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux)
 	return 1;
 }
 
+static const struct nvkm_ior_func_dp
+nv50_pior_dp = {
+	.links = nv50_pior_dp_links,
+};
+
 static void
 nv50_pior_power_wait(struct nvkm_device *device, u32 poff)
 {
@@ -139,9 +144,7 @@ nv50_pior = {
 	.state = nv50_pior_state,
 	.power = nv50_pior_power,
 	.clock = nv50_pior_clock,
-	.dp = {
-		.links = nv50_pior_dp_links,
-	},
+	.dp = &nv50_pior_dp,
 };
 
 int
@@ -1324,7 +1327,7 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior)
 	do_div(v, khz);
 	v = v - ((36 / ior->dp.nr) + 3) - 1;
 
-	ior->func->dp.audio_sym(ior, head->id, h, v);
+	ior->func->dp->audio_sym(ior, head->id, h, v);
 
 	/* watermark / activesym */
 	link_data_rate = (khz * head->asy.or.depth / 8) / ior->dp.nr;
@@ -1333,7 +1336,7 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior)
 	link_ratio = link_data_rate * symbol;
 	do_div(link_ratio, linkKBps);
 
-	for (TU = 64; ior->func->dp.activesym && TU >= 32; TU--) {
+	for (TU = 64; ior->func->dp->activesym && TU >= 32; TU--) {
 		/* calculate average number of valid symbols in each TU */
 		u32 tu_valid = link_ratio * TU;
 		u32 calc, diff;
@@ -1384,13 +1387,13 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior)
 		}
 	}
 
-	if (ior->func->dp.activesym) {
+	if (ior->func->dp->activesym) {
 		if (!bestTU) {
 			nvkm_error(subdev, "unable to determine dp config\n");
 			return;
 		}
-		ior->func->dp.activesym(ior, head->id, bestTU,
-					bestVTUa, bestVTUf, bestVTUi);
+
+		ior->func->dp->activesym(ior, head->id, bestTU, bestVTUa, bestVTUf, bestVTUi);
 	} else {
 		bestTU = 64;
 	}
@@ -1402,7 +1405,7 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior)
 	do_div(unk, symbol);
 	unk += 6;
 
-	ior->func->dp.watermark(ior, head->id, unk);
+	ior->func->dp->watermark(ior, head->id, unk);
 }
 
 void
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
index 9d231b07f752..a23040d26079 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
@@ -151,12 +151,12 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
 
 		if (size && args->v0.data[0]) {
 			if (outp->info.type == DCB_OUTPUT_DP)
-				ior->func->dp.audio(ior, hidx, true);
+				ior->func->dp->audio(ior, hidx, true);
 			ior->func->hda.hpd(ior, hidx, true);
 			ior->func->hda.eld(ior, hidx, data, size);
 		} else {
 			if (outp->info.type == DCB_OUTPUT_DP)
-				ior->func->dp.audio(ior, hidx, false);
+				ior->func->dp->audio(ior, hidx, false);
 			ior->func->hda.hpd(ior, hidx, false);
 		}
 
@@ -251,9 +251,9 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
 				   args->v0.version, args->v0.start_slot,
 				   args->v0.num_slots, args->v0.pbn,
 				   args->v0.aligned_pbn);
-			if (!outp->ior->func->dp.vcpi)
+			if (!outp->ior->func->dp->vcpi)
 				return -ENODEV;
-			outp->ior->func->dp.vcpi(outp->ior, hidx,
+			outp->ior->func->dp->vcpi(outp->ior, hidx,
 						 args->v0.start_slot,
 						 args->v0.num_slots,
 						 args->v0.pbn,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
index febc9090632f..236176573cee 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
@@ -66,6 +66,19 @@ tu102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
 	return 0;
 }
 
+static const struct nvkm_ior_func_dp
+tu102_sor_dp = {
+	.lanes = { 0, 1, 2, 3 },
+	.links = tu102_sor_dp_links,
+	.power = g94_sor_dp_power,
+	.pattern = gm107_sor_dp_pattern,
+	.drive = gm200_sor_dp_drive,
+	.vcpi = tu102_sor_dp_vcpi,
+	.audio = gv100_sor_dp_audio,
+	.audio_sym = gv100_sor_dp_audio_sym,
+	.watermark = gv100_sor_dp_watermark,
+};
+
 static const struct nvkm_ior_func
 tu102_sor = {
 	.route = {
@@ -79,17 +92,7 @@ tu102_sor = {
 		.ctrl = gv100_sor_hdmi_ctrl,
 		.scdc = gm200_sor_hdmi_scdc,
 	},
-	.dp = {
-		.lanes = { 0, 1, 2, 3 },
-		.links = tu102_sor_dp_links,
-		.power = g94_sor_dp_power,
-		.pattern = gm107_sor_dp_pattern,
-		.drive = gm200_sor_dp_drive,
-		.vcpi = tu102_sor_dp_vcpi,
-		.audio = gv100_sor_dp_audio,
-		.audio_sym = gv100_sor_dp_audio_sym,
-		.watermark = gv100_sor_dp_watermark,
-	},
+	.dp = &tu102_sor_dp,
 	.hda = {
 		.hpd = gf119_sor_hda_hpd,
 		.eld = gf119_sor_hda_eld,
-- 
2.38.1