[PATCH 1/5] drm/dp: Add drm_dp_hdr_metadata_infoframe_sdp_pack()
From: Igor Paunovic
Date: Sat Aug 08 2026 - 05:58:29 EST
i915 packs HDR static metadata into an HDR Metadata InfoFrame SDP
(DP 1.4a spec, Table 2-100 and Table 2-101) with a driver-private
helper, intel_dp_hdr_metadata_infoframe_sdp_pack(). Nothing in it is
i915 specific: it converts a generic struct hdmi_drm_infoframe into a
generic struct dp_sdp.
Move it to drm_dp_helper.c as drm_dp_hdr_metadata_infoframe_sdp_pack(),
next to drm_dp_vsc_sdp_pack(), and convert i915 to the new helper. The
Synopsys DesignWare DisplayPort bridge driver (dw-dp) needs to send the
same SDP to support HDR and should not have to duplicate the packing
code.
The helper takes a struct drm_device pointer in place of the i915
display pointer for its two debug messages, and an i915-specific
comment about GEN11+ GMP register sizes is dropped. No functional
change.
Signed-off-by: Igor Paunovic <royalnet026@xxxxxxxxx>
---
drivers/gpu/drm/display/drm_dp_helper.c | 88 +++++++++++++++++++++++++
drivers/gpu/drm/i915/display/intel_dp.c | 84 +----------------------
include/drm/display/drm_dp_helper.h | 4 ++
3 files changed, 95 insertions(+), 81 deletions(-)
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index 9c31e14cc413..7b3b079403c4 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -25,6 +25,7 @@
#include <linux/dynamic_debug.h>
#include <linux/errno.h>
#include <linux/export.h>
+#include <linux/hdmi.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/iopoll.h>
@@ -3672,6 +3673,93 @@ ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
}
EXPORT_SYMBOL(drm_dp_vsc_sdp_pack);
+/**
+ * drm_dp_hdr_metadata_infoframe_sdp_pack() - pack HDR Metadata InfoFrame SDP
+ * @dev: DRM device
+ * @drm_infoframe: HDMI DRM infoframe carrying the HDR static metadata
+ * @sdp: valid handle to the generic dp_sdp which will be packed
+ * @size: valid size of the passed sdp handle
+ *
+ * Pack a CTA-861 Dynamic Range and Mastering infoframe into an HDR
+ * Metadata InfoFrame SDP, as defined in DP 1.4a spec, Table 2-100 and
+ * Table 2-101.
+ *
+ * Returns: length of sdp on success and error code on failure
+ */
+ssize_t drm_dp_hdr_metadata_infoframe_sdp_pack(struct drm_device *dev,
+ const struct hdmi_drm_infoframe *drm_infoframe,
+ struct dp_sdp *sdp,
+ size_t size)
+{
+ size_t length = sizeof(struct dp_sdp);
+ const int infoframe_size = HDMI_INFOFRAME_HEADER_SIZE + HDMI_DRM_INFOFRAME_SIZE;
+ unsigned char buf[HDMI_INFOFRAME_HEADER_SIZE + HDMI_DRM_INFOFRAME_SIZE];
+ ssize_t len;
+
+ if (size < length)
+ return -ENOSPC;
+
+ memset(sdp, 0, size);
+
+ len = hdmi_drm_infoframe_pack_only(drm_infoframe, buf, sizeof(buf));
+ if (len < 0) {
+ drm_dbg_kms(dev,
+ "buffer size is smaller than hdr metadata infoframe\n");
+ return -ENOSPC;
+ }
+
+ if (len != infoframe_size) {
+ drm_dbg_kms(dev, "wrong static hdr metadata size\n");
+ return -ENOSPC;
+ }
+
+ /*
+ * Set up the infoframe sdp packet for HDR static metadata.
+ * Prepare VSC Header for SU as per DP 1.4a spec,
+ * Table 2-100 and Table 2-101
+ */
+
+ /* Secondary-Data Packet ID, 00h for non-Audio INFOFRAME */
+ sdp->sdp_header.HB0 = 0;
+ /*
+ * Packet Type 80h + Non-audio INFOFRAME Type value
+ * HDMI_INFOFRAME_TYPE_DRM: 0x87
+ * - 80h + Non-audio INFOFRAME Type value
+ * - InfoFrame Type: 0x07
+ * [CTA-861-G Table-42 Dynamic Range and Mastering InfoFrame]
+ */
+ sdp->sdp_header.HB1 = drm_infoframe->type;
+ /*
+ * Least Significant Eight Bits of (Data Byte Count – 1)
+ * infoframe_size - 1
+ */
+ sdp->sdp_header.HB2 = 0x1D;
+ /* INFOFRAME SDP Version Number */
+ sdp->sdp_header.HB3 = (0x13 << 2);
+ /* CTA Header Byte 2 (INFOFRAME Version Number) */
+ sdp->db[0] = drm_infoframe->version;
+ /* CTA Header Byte 3 (Length of INFOFRAME): HDMI_DRM_INFOFRAME_SIZE */
+ sdp->db[1] = drm_infoframe->length;
+ /*
+ * Copy HDMI_DRM_INFOFRAME_SIZE size from a buffer after
+ * HDMI_INFOFRAME_HEADER_SIZE
+ */
+ BUILD_BUG_ON(sizeof(sdp->db) < HDMI_DRM_INFOFRAME_SIZE + 2);
+ memcpy(&sdp->db[2], &buf[HDMI_INFOFRAME_HEADER_SIZE],
+ HDMI_DRM_INFOFRAME_SIZE);
+
+ /*
+ * Size of DP infoframe sdp packet for HDR static metadata consists of
+ * - DP SDP Header(struct dp_sdp_header): 4 bytes
+ * - Two Data Blocks: 2 bytes
+ * CTA Header Byte2 (INFOFRAME Version Number)
+ * CTA Header Byte3 (Length of INFOFRAME)
+ * - HDMI_DRM_INFOFRAME_SIZE: 26 bytes
+ */
+ return sizeof(struct dp_sdp_header) + 2 + HDMI_DRM_INFOFRAME_SIZE;
+}
+EXPORT_SYMBOL(drm_dp_hdr_metadata_infoframe_sdp_pack);
+
/**
* drm_dp_get_pcon_max_frl_bw() - maximum frl supported by PCON
* @dpcd: DisplayPort configuration data
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 6e3fa6662cbe..093a3b7961f7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5157,84 +5157,6 @@ static ssize_t intel_dp_as_sdp_pack(const struct drm_dp_as_sdp *as_sdp,
return length;
}
-static ssize_t
-intel_dp_hdr_metadata_infoframe_sdp_pack(struct intel_display *display,
- const struct hdmi_drm_infoframe *drm_infoframe,
- struct dp_sdp *sdp,
- size_t size)
-{
- size_t length = sizeof(struct dp_sdp);
- const int infoframe_size = HDMI_INFOFRAME_HEADER_SIZE + HDMI_DRM_INFOFRAME_SIZE;
- unsigned char buf[HDMI_INFOFRAME_HEADER_SIZE + HDMI_DRM_INFOFRAME_SIZE];
- ssize_t len;
-
- if (size < length)
- return -ENOSPC;
-
- memset(sdp, 0, size);
-
- len = hdmi_drm_infoframe_pack_only(drm_infoframe, buf, sizeof(buf));
- if (len < 0) {
- drm_dbg_kms(display->drm,
- "buffer size is smaller than hdr metadata infoframe\n");
- return -ENOSPC;
- }
-
- if (len != infoframe_size) {
- drm_dbg_kms(display->drm, "wrong static hdr metadata size\n");
- return -ENOSPC;
- }
-
- /*
- * Set up the infoframe sdp packet for HDR static metadata.
- * Prepare VSC Header for SU as per DP 1.4a spec,
- * Table 2-100 and Table 2-101
- */
-
- /* Secondary-Data Packet ID, 00h for non-Audio INFOFRAME */
- sdp->sdp_header.HB0 = 0;
- /*
- * Packet Type 80h + Non-audio INFOFRAME Type value
- * HDMI_INFOFRAME_TYPE_DRM: 0x87
- * - 80h + Non-audio INFOFRAME Type value
- * - InfoFrame Type: 0x07
- * [CTA-861-G Table-42 Dynamic Range and Mastering InfoFrame]
- */
- sdp->sdp_header.HB1 = drm_infoframe->type;
- /*
- * Least Significant Eight Bits of (Data Byte Count – 1)
- * infoframe_size - 1
- */
- sdp->sdp_header.HB2 = 0x1D;
- /* INFOFRAME SDP Version Number */
- sdp->sdp_header.HB3 = (0x13 << 2);
- /* CTA Header Byte 2 (INFOFRAME Version Number) */
- sdp->db[0] = drm_infoframe->version;
- /* CTA Header Byte 3 (Length of INFOFRAME): HDMI_DRM_INFOFRAME_SIZE */
- sdp->db[1] = drm_infoframe->length;
- /*
- * Copy HDMI_DRM_INFOFRAME_SIZE size from a buffer after
- * HDMI_INFOFRAME_HEADER_SIZE
- */
- BUILD_BUG_ON(sizeof(sdp->db) < HDMI_DRM_INFOFRAME_SIZE + 2);
- memcpy(&sdp->db[2], &buf[HDMI_INFOFRAME_HEADER_SIZE],
- HDMI_DRM_INFOFRAME_SIZE);
-
- /*
- * Size of DP infoframe sdp packet for HDR static metadata consists of
- * - DP SDP Header(struct dp_sdp_header): 4 bytes
- * - Two Data Blocks: 2 bytes
- * CTA Header Byte2 (INFOFRAME Version Number)
- * CTA Header Byte3 (Length of INFOFRAME)
- * - HDMI_DRM_INFOFRAME_SIZE: 26 bytes
- *
- * Prior to GEN11's GMP register size is identical to DP HDR static metadata
- * infoframe size. But GEN11+ has larger than that size, write_infoframe
- * will pad rest of the size.
- */
- return sizeof(struct dp_sdp_header) + 2 + HDMI_DRM_INFOFRAME_SIZE;
-}
-
static void intel_write_dp_sdp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type)
@@ -5253,9 +5175,9 @@ static void intel_write_dp_sdp(struct intel_encoder *encoder,
len = drm_dp_vsc_sdp_pack(&crtc_state->infoframes.vsc, &sdp);
break;
case HDMI_PACKET_TYPE_GAMUT_METADATA:
- len = intel_dp_hdr_metadata_infoframe_sdp_pack(display,
- &crtc_state->infoframes.drm.drm,
- &sdp, sizeof(sdp));
+ len = drm_dp_hdr_metadata_infoframe_sdp_pack(display->drm,
+ &crtc_state->infoframes.drm.drm,
+ &sdp, sizeof(sdp));
break;
case DP_SDP_ADAPTIVE_SYNC:
len = intel_dp_as_sdp_pack(&crtc_state->infoframes.as_sdp, &sdp,
diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
index ab16c1be3900..c158628f0d38 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -32,6 +32,7 @@
struct drm_device;
struct drm_dp_aux;
struct drm_panel;
+struct hdmi_drm_infoframe;
bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
int lane_count);
@@ -1029,6 +1030,9 @@ int drm_dp_bw_channel_coding_efficiency(bool is_uhbr);
int drm_dp_max_dprx_data_rate(int max_link_rate, int max_lanes);
ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc, struct dp_sdp *sdp);
+ssize_t drm_dp_hdr_metadata_infoframe_sdp_pack(struct drm_device *dev,
+ const struct hdmi_drm_infoframe *drm_infoframe,
+ struct dp_sdp *sdp, size_t size);
int drm_dp_link_symbol_cycles(int lane_count, int pixels, int dsc_slice_count,
int bpp_x16, int symbol_size, bool is_mst);
--
2.43.0