[Nouveau] [PATCH 1/6] drm/nouveau: Extend NVKM HDMI power control method to set InfoFrames

Alastair Bridgewater alastair.bridgewater at gmail.com
Tue Jan 17 22:41:59 UTC 2017


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 at gmail.com>
---
 drivers/gpu/drm/nouveau/include/nvif/cl5070.h      | 16 ++++++++++-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c | 32 +++++++++++++++++++++-
 .../gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c   | 32 +++++++++++++++++++++-
 .../gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c   | 32 +++++++++++++++++++++-
 .../gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c   | 32 +++++++++++++++++++++-
 5 files changed, 139 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
index ae49dfd..a3ce3bf 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
@@ -76,7 +76,21 @@ struct nv50_disp_sor_hdmi_pwr_v0 {
 	__u8  state;
 	__u8  max_ac_packet;
 	__u8  rekey;
-	__u8  pad04[4];
+	__u8  flags;
+#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME     0x01
+#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME       0x02
+#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME    0x04
+	__u8  pad05[3];
+};
+
+struct nv50_disp_sor_hdmi_pwr_v0_infoframe {
+	__u8  version;
+	__u8  pad01[3];
+	__u32 header;
+	__u32 subpack0_low;
+	__u32 subpack0_high;
+	__u32 subpack1_low;
+	__u32 subpack1_high;
 };
 
 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 1c4256e..f767588 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
@@ -36,11 +36,14 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	union {
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *audio_infoframe = NULL;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *avi_infoframe = NULL;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *vendor_infoframe = NULL;
 	u32 ctrl;
 	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 +57,33 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	} else
 		return ret;
 
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME) {
+		audio_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *audio_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME) {
+		avi_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *avi_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME) {
+		vendor_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *vendor_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (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 632f02d..c492cd7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
@@ -36,11 +36,14 @@ gf119_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	union {
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *audio_infoframe = NULL;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *avi_infoframe = NULL;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *vendor_infoframe = NULL;
 	u32 ctrl;
 	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 +56,33 @@ gf119_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	} else
 		return ret;
 
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME) {
+		audio_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *audio_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME) {
+		avi_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *avi_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME) {
+		vendor_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *vendor_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (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 4e8067d..6c38d6d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
@@ -37,11 +37,14 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	union {
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *audio_infoframe = NULL;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *avi_infoframe = NULL;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *vendor_infoframe = NULL;
 	u32 ctrl;
 	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 +57,33 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	} else
 		return ret;
 
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME) {
+		audio_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *audio_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME) {
+		avi_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *avi_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME) {
+		vendor_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *vendor_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (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 f1afc16..e2fbe4c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
@@ -37,11 +37,14 @@ gt215_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	union {
 		struct nv50_disp_sor_hdmi_pwr_v0 v0;
 	} *args = data;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *audio_infoframe = NULL;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *avi_infoframe = NULL;
+	struct nv50_disp_sor_hdmi_pwr_v0_infoframe *vendor_infoframe = NULL;
 	u32 ctrl;
 	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 +58,33 @@ gt215_hdmi_ctrl(NV50_DISP_MTHD_V1)
 	} else
 		return ret;
 
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME) {
+		audio_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *audio_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME) {
+		avi_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *avi_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (args->v0.flags &
+	    NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME) {
+		vendor_infoframe = data;
+		if ((ret = nvif_unpack(-ENOSYS, &data, &size,
+				       *vendor_infoframe, 0, 0, true)))
+			return ret;
+	}
+
+	if (size)
+		return -E2BIG;
+
 	if (!(ctrl & 0x40000000)) {
 		nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000);
 		nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000);
-- 
2.10.2



More information about the Nouveau mailing list