[PATCH 8/9] drm/i915: Sending AVI infoframe through GMP DIP

Ankit Nautiyal ankit.k.nautiyal at intel.com
Mon Oct 17 08:43:11 UTC 2022


From: Swati Sharma <swati2.sharma at intel.com>

DP does not support sending AVI info frame to panel. So we need to
send AVI info frame to HDMI through some other DIP.

When DP-to-HDMI protocol converter is present GMP DIP will be used
to send AVI infoframe instead of static HDR infoframes.

While VESA spec indicates support within PCON to built AVI IF, it
gives better control with source sending the infoframe by itself as
per HDMI/CTA spec. Minimum of version 3 need to be used for VIC >= 128
(i.e. for 8k mode as an example).

v2:
-Added the case for AVI infoframe type in intel_write_sdp (Gwan-gyeong Mun)
-Used the type AVI infoframe instead of GMP in crtc_state, and only used
type GMP while writing infoframe (Gwan-gyeong Mun).
-Avoided writing the AVI infoframe Header twice in sdp packet (Ankit).
-Corrected the buffer size for AVI infoframe packing (Ankit).

v3: Rebased

Signed-off-by: Swati Sharma <swati2.sharma at intel.com>
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 80 ++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 6b0f05797bfb..7b60fce65fba 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2008,6 +2008,17 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
 	return ret;
 }
 
+static void
+intel_dp_compute_avi_infoframe_sdp(struct intel_encoder *encoder,
+				   struct intel_crtc_state *crtc_state,
+				   struct drm_connector_state *conn_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+
+	if (!intel_hdmi_compute_avi_infoframe(encoder, crtc_state, conn_state))
+		drm_dbg_kms(&dev_priv->drm, "Bad AVI infoframe\n");
+}
+
 int
 intel_dp_compute_config(struct intel_encoder *encoder,
 			struct intel_crtc_state *pipe_config,
@@ -2109,7 +2120,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	intel_psr_compute_config(intel_dp, pipe_config, conn_state);
 	intel_dp_drrs_compute_config(connector, pipe_config, output_bpp);
 	intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
-	intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state);
+
+	if (intel_dp_is_hdmi_2_1_sink(intel_dp)) {
+		pipe_config->has_infoframe = true;
+		intel_dp_compute_avi_infoframe_sdp(encoder, pipe_config, conn_state);
+	} else {
+		intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state);
+	}
 
 	return 0;
 }
@@ -3197,12 +3214,60 @@ intel_dp_hdr_metadata_infoframe_sdp_pack(struct drm_i915_private *i915,
 	return sizeof(struct dp_sdp_header) + 2 + HDMI_DRM_INFOFRAME_SIZE;
 }
 
+static ssize_t
+intel_dp_avi_infoframe_sdp_pack(const struct hdmi_avi_infoframe *avi_infoframe,
+				struct dp_sdp *sdp, size_t size)
+{
+	size_t length = sizeof(struct dp_sdp);
+	const int infoframe_size = HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE;
+	unsigned char buf[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
+	ssize_t len;
+
+	if (size < length)
+		return -ENOSPC;
+
+	memset(sdp, 0, size);
+
+	len = hdmi_avi_infoframe_pack_only(avi_infoframe, buf, sizeof(buf));
+	if (len < 0) {
+		DRM_DEBUG_KMS("buffer size is smaller than avi infoframe\n");
+		return -ENOSPC;
+	}
+
+	if (len != infoframe_size) {
+		DRM_DEBUG_KMS("wrong avi infoframe size\n");
+		return -ENOSPC;
+	}
+
+	sdp->sdp_header.HB0 = 0;
+	sdp->sdp_header.HB1 = avi_infoframe->type;
+	sdp->sdp_header.HB2 = 0x1D;
+	sdp->sdp_header.HB3 = (0x13 << 2);
+	sdp->db[0] = avi_infoframe->version;
+	sdp->db[1] = avi_infoframe->length;
+
+	BUILD_BUG_ON(sizeof(sdp->db) < HDMI_AVI_INFOFRAME_SIZE + 2);
+	memcpy(&sdp->db[2], &buf[HDMI_INFOFRAME_HEADER_SIZE], HDMI_AVI_INFOFRAME_SIZE);
+
+	 /*
+	  * Size of DP infoframe sdp packet for AVI Infoframe 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_AVI_INFOFRAME_SIZE: 13 bytes
+	  */
+
+	return sizeof(struct dp_sdp_header) + 2 + HDMI_AVI_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 *dig_port = enc_to_dig_port(encoder);
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct dp_sdp sdp = {};
 	ssize_t len;
 
@@ -3216,10 +3281,22 @@ static void intel_write_dp_sdp(struct intel_encoder *encoder,
 					    sizeof(sdp));
 		break;
 	case HDMI_PACKET_TYPE_GAMUT_METADATA:
+		if (intel_dp_is_hdmi_2_1_sink(intel_dp))
+			return;
+
 		len = intel_dp_hdr_metadata_infoframe_sdp_pack(dev_priv,
 							       &crtc_state->infoframes.drm.drm,
 							       &sdp, sizeof(sdp));
 		break;
+	case HDMI_INFOFRAME_TYPE_AVI:
+		if (!intel_dp_is_hdmi_2_1_sink(intel_dp))
+			return;
+
+		len = intel_dp_avi_infoframe_sdp_pack(&crtc_state->infoframes.avi.avi, &sdp,
+						      sizeof(sdp));
+		/* SDP DIP type GMP to be used for AVI Infoframe */
+		type = HDMI_PACKET_TYPE_GAMUT_METADATA;
+		break;
 	default:
 		MISSING_CASE(type);
 		return;
@@ -3277,6 +3354,7 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder,
 		intel_write_dp_sdp(encoder, crtc_state, DP_SDP_VSC);
 
 	intel_write_dp_sdp(encoder, crtc_state, HDMI_PACKET_TYPE_GAMUT_METADATA);
+	intel_write_dp_sdp(encoder, crtc_state, HDMI_INFOFRAME_TYPE_AVI);
 }
 
 static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc,
-- 
2.25.1



More information about the Intel-gfx-trybot mailing list