Blob Blame History Raw
From f60213c0ee93ffb89a64bad9a5db52e854530b1d Mon Sep 17 00:00:00 2001
From: Alastair Bridgewater <alastair.bridgewater@gmail.com>
Date: Tue, 11 Apr 2017 13:11:19 -0400
Subject: [PATCH] drm/nouveau/disp: Add mechanism to convert HDMI InfoFrames to hardware format
Git-commit: f60213c0ee93ffb89a64bad9a5db52e854530b1d
Patch-mainline: v4.13-rc1
References: bsc#1095094

HDMI InfoFrames are passed to NVKM as bags of bytes, but the
hardware needs them to be packed into words.  Rather than having
four (or more) copies of the packing logic introduce a single copy
now, in a central place.

We currently need these for AVI and Vendor InfoFrames, but we may
also expect to need them for Audio InfoFrames at some point.

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/Kbuild           |    1 
 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi_infoframe.c |   66 ++++++++++++++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h           |   11 ++
 3 files changed, 78 insertions(+)
 create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi_infoframe.c

--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
@@ -29,6 +29,7 @@ nvkm-y += nvkm/engine/disp/conn.o
 nvkm-y += nvkm/engine/disp/hdagt215.o
 nvkm-y += nvkm/engine/disp/hdagf119.o
 
+nvkm-y += nvkm/engine/disp/hdmi_infoframe.o
 nvkm-y += nvkm/engine/disp/hdmig84.o
 nvkm-y += nvkm/engine/disp/hdmigt215.o
 nvkm-y += nvkm/engine/disp/hdmigf119.o
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmi_infoframe.c
@@ -0,0 +1,66 @@
+#include "nv50.h"
+
+void pack_hdmi_infoframe(struct packed_hdmi_infoframe *packed_frame,
+			 u8 *raw_frame, ssize_t len)
+{
+	u32 header = 0;
+	u32 subpack0_low = 0;
+	u32 subpack0_high = 0;
+	u32 subpack1_low = 0;
+	u32 subpack1_high = 0;
+
+	switch (len) {
+		/*
+		 * "When in doubt, use brute force."
+		 *     -- Ken Thompson.
+		 */
+	default:
+		/*
+		 * We presume that no valid frame is longer than 17
+		 * octets, including header...  And truncate to that
+		 * if it's longer.
+		 */
+	case 17:
+		subpack1_high = (raw_frame[16] << 16);
+	case 16:
+		subpack1_high |= (raw_frame[15] << 8);
+	case 15:
+		subpack1_high |= raw_frame[14];
+	case 14:
+		subpack1_low = (raw_frame[13] << 24);
+	case 13:
+		subpack1_low |= (raw_frame[12] << 16);
+	case 12:
+		subpack1_low |= (raw_frame[11] << 8);
+	case 11:
+		subpack1_low |= raw_frame[10];
+	case 10:
+		subpack0_high = (raw_frame[9] << 16);
+	case 9:
+		subpack0_high |= (raw_frame[8] << 8);
+	case 8:
+		subpack0_high |= raw_frame[7];
+	case 7:
+		subpack0_low = (raw_frame[6] << 24);
+	case 6:
+		subpack0_low |= (raw_frame[5] << 16);
+	case 5:
+		subpack0_low |= (raw_frame[4] << 8);
+	case 4:
+		subpack0_low |= raw_frame[3];
+	case 3:
+		header = (raw_frame[2] << 16);
+	case 2:
+		header |= (raw_frame[1] << 8);
+	case 1:
+		header |= raw_frame[0];
+	case 0:
+		break;
+	}
+
+	packed_frame->header = header;
+	packed_frame->subpack0_low = subpack0_low;
+	packed_frame->subpack0_high = subpack0_high;
+	packed_frame->subpack1_low = subpack1_low;
+	packed_frame->subpack1_high = subpack1_high;
+}
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
@@ -40,6 +40,17 @@ int nv50_dac_sense(NV50_DISP_MTHD_V1);
 int gt215_hda_eld(NV50_DISP_MTHD_V1);
 int gf119_hda_eld(NV50_DISP_MTHD_V1);
 
+struct packed_hdmi_infoframe {
+	u32 header;
+	u32 subpack0_low;
+	u32 subpack0_high;
+	u32 subpack1_low;
+	u32 subpack1_high;
+};
+
+void pack_hdmi_infoframe(struct packed_hdmi_infoframe *packed_frame,
+			 u8 *raw_frame, ssize_t len);
+
 int g84_hdmi_ctrl(NV50_DISP_MTHD_V1);
 int gt215_hdmi_ctrl(NV50_DISP_MTHD_V1);
 int gf119_hdmi_ctrl(NV50_DISP_MTHD_V1);