CTA-861-H requires that when a source ends Dynamic Range and Mastering InfoFrame transmission, it shall send a DRM infoframe with EOTF=0 and all metadata fields set to 0 for at least 2 seconds before stopping.
Currently, when transitioning from HDR to SDR, the driver abruptly stops sending the DRM metadata SDP/infoframe. This causes DP-to-HDMI converters to latch the previous HDR metadata and continue forwarding it to the HDMI sink, resulting in color errors (e.g. oversaturated or washed-out colors) on SDR content. Windows correctly implements the null infoframe transition. Fix both the DP and native HDMI paths to send a zeroed DRM infoframe (EOTF=Traditional_SDR=0, all luminance and primaries fields zero) when transitioning from HDR to SDR. The null packet is only sent when the previous connector state had HDR metadata active, avoiding unnecessary DRM infoframe transmission during normal SDR operation. Signed-off-by: Xiao Lu <[email protected]> --- drivers/gpu/drm/i915/display/intel_dp.c | 23 ++++++++++++++++++++--- drivers/gpu/drm/i915/display/intel_hdmi.c | 19 ++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 113d767e62e9..d5ed96ba7e7b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3231,14 +3231,29 @@ intel_dp_in_hdr_mode(const struct drm_connector_state *conn_state) static void intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) + const struct drm_connector_state *conn_state, + const struct drm_connector_state *old_conn_state) { struct intel_display *display = to_intel_display(intel_dp); int ret; struct hdmi_drm_infoframe *drm_infoframe = &crtc_state->infoframes.drm.drm; - if (!conn_state->hdr_output_metadata) + if (!conn_state->hdr_output_metadata) { + /* + * CTA-861-H requires ending HDR metadata transmission by + * sending a DRM infoframe with EOTF=0 and all fields zero + * for at least 2 seconds, rather than abruptly stopping. + * Abruptly stopping causes DP-to-HDMI converters to latch + * the previous HDR metadata and forward it to the HDMI sink, + * resulting in color errors on SDR content. + */ + if (old_conn_state && old_conn_state->hdr_output_metadata) { + hdmi_drm_infoframe_init(drm_infoframe); + crtc_state->infoframes.enable |= + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA); + } return; + } ret = drm_hdmi_infoframe_set_hdr_metadata(drm_infoframe, conn_state); @@ -3644,7 +3659,9 @@ intel_dp_compute_config(struct intel_atomic_state *state, intel_alpm_lobf_compute_config(intel_dp, pipe_config, conn_state); intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16); intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); - intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state); + intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state, + drm_atomic_get_old_connector_state(&state->base, + conn_state->connector)); return intel_dp_tunnel_atomic_compute_stream_bw(state, intel_dp, connector, pipe_config); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 8a019d3574df..9fb9be302d35 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -856,8 +856,25 @@ intel_hdmi_compute_drm_infoframe(struct intel_encoder *encoder, if (!crtc_state->has_infoframe) return true; - if (!conn_state->hdr_output_metadata) + if (!conn_state->hdr_output_metadata) { + const struct drm_connector_state *old_conn_state = + drm_atomic_get_old_connector_state(conn_state->state, + conn_state->connector); + /* + * CTA-861-H requires ending HDR metadata transmission by + * sending a DRM infoframe with EOTF=0 and all fields zero + * for at least 2 seconds, rather than abruptly stopping. + * Abruptly stopping causes DP-to-HDMI converters to latch + * the previous HDR metadata and forward it to the HDMI sink, + * resulting in color errors on SDR content. + */ + if (old_conn_state && old_conn_state->hdr_output_metadata) { + hdmi_drm_infoframe_init(frame); + crtc_state->infoframes.enable |= + intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM); + } return true; + } crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM); -- 2.43.0
