Blob Blame History Raw
From a8970743502f6e52297fca4181ae524041119106 Mon Sep 17 00:00:00 2001
From: Alastair Bridgewater <alastair.bridgewater@gmail.com>
Date: Tue, 11 Apr 2017 13:11:23 -0400
Subject: [PATCH] drm/nouveau/disp/gk104-: Use supplied HDMI InfoFrames
Git-commit: a8970743502f6e52297fca4181ae524041119106
Patch-mainline: v4.13-rc1
References: bsc#1095094

Now that we have the InfoFrame data being provided, for the most
part, program the hardware to use it.

While we're here, and since the functionality will come in handy
for supporting 3D stereoscopy, implement setting the Vendor
("generic"?) InfoFrame.

Also don't enable any InfoFrame that is not provided, and disable
the Vendor InfoFrame when disabling the output.

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

---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c |   36 +++++++++++++++----
 1 file changed, 30 insertions(+), 6 deletions(-)

--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
@@ -37,6 +37,8 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	union {
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
+	struct packed_hdmi_infoframe avi_infoframe;
+	struct packed_hdmi_infoframe vendor_infoframe;
 	u32 ctrl;
 	int ret = -ENOSYS;
 
@@ -61,8 +63,17 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
 		    + args->v0.vendor_infoframe_length) < size)
 		return -E2BIG;
 
+	pack_hdmi_infoframe(&avi_infoframe,
+			    data,
+			    args->v0.avi_infoframe_length);
+
+	pack_hdmi_infoframe(&vendor_infoframe,
+			    data + args->v0.avi_infoframe_length,
+			    args->v0.vendor_infoframe_length);
+
 	if (!(ctrl & 0x40000000)) {
 		nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000);
+		nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000000);
 		nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000);
 		nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000);
 		return 0;
@@ -70,12 +81,25 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
 
 	/* AVI InfoFrame */
 	nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000);
-	nvkm_wr32(device, 0x690008 + hdmi, 0x000d0282);
-	nvkm_wr32(device, 0x69000c + hdmi, 0x0000006f);
-	nvkm_wr32(device, 0x690010 + hdmi, 0x00000000);
-	nvkm_wr32(device, 0x690014 + hdmi, 0x00000000);
-	nvkm_wr32(device, 0x690018 + hdmi, 0x00000000);
-	nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001);
+	if (args->v0.avi_infoframe_length) {
+		nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header);
+		nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low);
+		nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high);
+		nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low);
+		nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high);
+		nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001);
+	}
+
+	/* GENERIC(?) / Vendor InfoFrame? */
+	nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000);
+	if (args->v0.vendor_infoframe_length) {
+		nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header);
+		nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low);
+		nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high);
+		/* Is there a second (or further?) set of subpack registers here? */
+		nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001);
+	}
+
 
 	/* ??? InfoFrame? */
 	nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000);