Re: [PATCH 1/5] drm/dp: Add drm_dp_hdr_metadata_infoframe_sdp_pack()

From: Jani Nikula

Date: Mon Aug 10 2026 - 05:00:45 EST


On Sat, 08 Aug 2026, Igor Paunovic <royalnet026@xxxxxxxxx> wrote:
> 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>

'git show --color-moved' says it's fine. ;)

Acked-by: Jani Nikula <jani.nikula@xxxxxxxxx>

for merging via drm-misc.

> ---
> 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);

--
Jani Nikula, Intel