return false;
 }
 
+static ssize_t intel_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
+                                    struct dp_sdp *sdp, size_t size)
+{
+       size_t length = sizeof(struct dp_sdp);
+
+       if (size < length)
+               return -ENOSPC;
+
+       memset(sdp, 0, size);
+
+       /*
+        * Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
+        * VSC SDP Header Bytes
+        */
+       sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
+       sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type */
+       sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
+       sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
+
+       /* VSC SDP Payload for DB16 through DB18 */
+       /* Pixel Encoding and Colorimetry Formats  */
+       sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
+       sdp->db[16] |= vsc->colorimetry & 0xf; /* DB16[3:0] */
+
+       switch (vsc->bpc) {
+       case 6:
+               /* 6bpc: 0x0 */
+               break;
+       case 8:
+               sdp->db[17] = 0x1; /* DB17[3:0] */
+               break;
+       case 10:
+               sdp->db[17] = 0x2;
+               break;
+       case 12:
+               sdp->db[17] = 0x3;
+               break;
+       case 16:
+               sdp->db[17] = 0x4;
+               break;
+       default:
+               MISSING_CASE(vsc->bpc);
+               break;
+       }
+       /* Dynamic Range and Component Bit Depth */
+       if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
+               sdp->db[17] |= 0x80;  /* DB17[7] */
+
+       /* Content Type */
+       sdp->db[18] = vsc->content_type & 0x7;
+
+       return length;
+}
+
+static ssize_t
+intel_dp_hdr_metadata_infoframe_sdp_pack(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_DEBUG_KMS("buffer size is smaller than hdr metadata infoframe\n");
+               return -ENOSPC;
+       }
+
+       if (len != infoframe_size) {
+               DRM_DEBUG_KMS("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)
+{
+       struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       struct dp_sdp sdp = {};
+       ssize_t len;
+
+       if ((crtc_state->infoframes.enable &
+            intel_hdmi_infoframe_enable(type)) == 0)
+               return;
+
+       switch (type) {
+       case DP_SDP_VSC:
+               len = intel_dp_vsc_sdp_pack(&crtc_state->infoframes.vsc, &sdp,
+                                           sizeof(sdp));
+               break;
+       case HDMI_PACKET_TYPE_GAMUT_METADATA:
+               len = intel_dp_hdr_metadata_infoframe_sdp_pack(&crtc_state->infoframes.drm.drm,
+                                                              &sdp, sizeof(sdp));
+               break;
+       default:
+               MISSING_CASE(type);
+               break;
+       }
+
+       if (drm_WARN_ON(&dev_priv->drm, len < 0))
+               return;
+
+       intel_dig_port->write_infoframe(encoder, crtc_state, type, &sdp, len);
+}
+
+void intel_dp_set_infoframes(struct intel_encoder *encoder,
+                            bool enable,
+                            const struct intel_crtc_state *crtc_state,
+                            const struct drm_connector_state *conn_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
+       u32 dip_enable = VIDEO_DIP_ENABLE_AVI_HSW | VIDEO_DIP_ENABLE_GCP_HSW |
+                        VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW |
+                        VIDEO_DIP_ENABLE_SPD_HSW | VIDEO_DIP_ENABLE_DRM_GLK;
+       u32 val = intel_de_read(dev_priv, reg);
+
+       /* TODO: Add DSC case (DIP_ENABLE_PPS) */
+       /* When PSR is enabled, this routine doesn't disable VSC DIP */
+       if (intel_psr_enabled(intel_dp))
+               val &= ~dip_enable;
+       else
+               val &= ~(dip_enable | VIDEO_DIP_ENABLE_VSC_HSW);
+
+       if (!enable) {
+               intel_de_write(dev_priv, reg, val);
+               intel_de_posting_read(dev_priv, reg);
+               return;
+       }
+
+       intel_de_write(dev_priv, reg, val);
+       intel_de_posting_read(dev_priv, reg);
+
+       /* When PSR is enabled, VSC SDP is handled by PSR routine */
+       if (!intel_psr_enabled(intel_dp))
+               intel_write_dp_sdp(encoder, crtc_state, DP_SDP_VSC);
+
+       intel_write_dp_sdp(encoder, crtc_state, HDMI_PACKET_TYPE_GAMUT_METADATA);
+}
+
 static void
 intel_dp_setup_vsc_sdp(struct intel_dp *intel_dp,
                       const struct intel_crtc_state *crtc_state,