Blob Blame History Raw
From 31fe2c200262a512255340d6f9493d51e06a8207 Mon Sep 17 00:00:00 2001
From: Alastair Bridgewater <alastair.bridgewater@gmail.com>
Date: Tue, 11 Apr 2017 13:11:17 -0400
Subject: [PATCH] drm/nouveau/disp/g84-: Extend NVKM HDMI power control method to set InfoFrames
Git-commit: 31fe2c200262a512255340d6f9493d51e06a8207
Patch-mainline: v4.13-rc1
References: bsc#1095094

The nouveau driver, in the Linux 3.7 days, used to try and set the
AVI InfoFrame based on the selected display mode.  These days, it
uses a fixed set of InfoFrames.  Start to correct that, by
providing a mechanism whereby InfoFrame data may be passed to the
NVKM functions that do the actual configuration.

At this point, only establish the new parameters and their parsing,
don't actually use the data anywhere yet (since it's not supplied
anywhere).

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/include/nvif/cl5070.h        | 4 +++-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c   | 9 ++++++++-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c | 9 ++++++++-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c | 9 ++++++++-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c | 9 ++++++++-
 5 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
index ae49dfd1f97b..9d46ebac58a2 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
@@ -76,7 +76,9 @@ struct nv50_disp_sor_hdmi_pwr_v0 {
 	__u8  state;
 	__u8  max_ac_packet;
 	__u8  rekey;
-	__u8  pad04[4];
+	__u8  avi_infoframe_length;
+	__u8  vendor_infoframe_length;
+	__u8  pad06[2];
 };
 
 struct nv50_disp_sor_lvds_script_v0 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
index 1c4256e8cbd6..77e5f5a2f3fa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
@@ -40,7 +40,7 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
-	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
 				   "max_ac_packet %d rekey %d\n",
 			   args->v0.version, args->v0.state,
@@ -54,6 +54,13 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	} else
 		return ret;
 
+	if ((args->v0.avi_infoframe_length
+	     + args->v0.vendor_infoframe_length) > size)
+		return -ENOSYS;
+	else if ((args->v0.avi_infoframe_length
+		    + args->v0.vendor_infoframe_length) < size)
+		return -E2BIG;
+
 	if (!(ctrl & 0x40000000)) {
 		nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000);
 		nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
index 632f02da1382..66ee88356e4e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
@@ -40,7 +40,7 @@ gf119_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
-	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
 				   "max_ac_packet %d rekey %d\n",
 			   args->v0.version, args->v0.state,
@@ -53,6 +53,13 @@ gf119_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	} else
 		return ret;
 
+	if ((args->v0.avi_infoframe_length
+	     + args->v0.vendor_infoframe_length) > size)
+		return -ENOSYS;
+	else if ((args->v0.avi_infoframe_length
+		    + args->v0.vendor_infoframe_length) < size)
+		return -E2BIG;
+
 	if (!(ctrl & 0x40000000)) {
 		nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000);
 		nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
index 4e8067d511d7..3c8c26a44f56 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
@@ -41,7 +41,7 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
-	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
 				   "max_ac_packet %d rekey %d\n",
 			   args->v0.version, args->v0.state,
@@ -54,6 +54,13 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	} else
 		return ret;
 
+	if ((args->v0.avi_infoframe_length
+	     + args->v0.vendor_infoframe_length) > size)
+		return -ENOSYS;
+	else if ((args->v0.avi_infoframe_length
+		    + args->v0.vendor_infoframe_length) < size)
+		return -E2BIG;
+
 	if (!(ctrl & 0x40000000)) {
 		nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000);
 		nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
index f1afc16494b6..8ed00dbf9dc1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
@@ -41,7 +41,7 @@ gt215_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	int ret = -ENOSYS;
 
 	nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
-	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+	if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 		nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
 				   "max_ac_packet %d rekey %d\n",
 			   args->v0.version, args->v0.state,
@@ -55,6 +55,13 @@ gt215_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	} else
 		return ret;
 
+	if ((args->v0.avi_infoframe_length
+	     + args->v0.vendor_infoframe_length) > size)
+		return -ENOSYS;
+	else if ((args->v0.avi_infoframe_length
+		    + args->v0.vendor_infoframe_length) < size)
+		return -E2BIG;
+
 	if (!(ctrl & 0x40000000)) {
 		nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000);
 		nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000);
-- 
2.17.0