i915_display_info prints per-connector state but not the current HDR
status. Add HDR details for each connector to the same debugfs file.

The HDR details are shown in three parts: sink capability, whether
userspace has set HDR_OUTPUT_METADATA, and whether the driver has
actually enabled HDR output.

Assisted-by: LLM
Signed-off-by: Pranay Samala <[email protected]>
---
 .../drm/i915/display/intel_display_debugfs.c  | 90 +++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 3e302f23f247..23c2f71f10eb 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/hdmi.h>
 #include <linux/string_choices.h>
 #include <linux/string_helpers.h>
 
@@ -243,6 +244,93 @@ static void intel_hdmi_info(struct seq_file *m,
        seq_printf(m, "\taudio support: %s\n", str_yes_no(has_audio));
 }
 
+static void intel_hdr_sink_info(struct drm_printer *p,
+                               struct drm_connector *connector)
+{
+       const struct hdr_static_metadata *hdr =
+               &connector->display_info.hdr_sink_metadata.hdmi_type1;
+       const struct drm_luminance_range_info *lum =
+               &connector->display_info.luminance_range;
+       int i;
+
+       /*
+        * Any transfer function other than the mandatory traditional gamma
+        * SDR one means the sink is declaring HDR support.
+        */
+       drm_printf_indent(p, 1, "HDR sink capable: %s\n",
+                         str_yes_no(hdr->eotf &
+                                    ~BIT(HDMI_EOTF_TRADITIONAL_GAMMA_SDR)));
+       if (!hdr->eotf)
+               return;
+
+       drm_printf_indent(p, 2, "supported EOTFs:\n");
+       for (i = HDMI_EOTF_TRADITIONAL_GAMMA_SDR; i <= HDMI_EOTF_BT_2100_HLG; 
i++)
+               if (hdr->eotf & BIT(i))
+                       drm_printf_indent(p, 3, "%s\n", hdmi_eotf_get_name(i));
+
+       drm_printf_indent(p, 2, "static metadata type1: %s\n",
+                         str_yes_no(hdr->metadata_type &
+                                    BIT(HDMI_STATIC_METADATA_TYPE1)));
+
+       /*
+        * The luminance fields are optional, and an EDID that omits them is
+        * indistinguishable from one declaring zero. luminance_range is only
+        * populated when they are actually present.
+        */
+       if (!lum->max_luminance) {
+               drm_printf_indent(p, 2, "luminance range: not specified\n");
+               return;
+       }
+
+       drm_printf_indent(p, 2, "luminance range: %u-%u nits\n",
+                         lum->min_luminance, lum->max_luminance);
+       drm_printf_indent(p, 2, "EDID max_cll: %u, max_fall: %u, min_cll: %u\n",
+                         hdr->max_cll, hdr->max_fall, hdr->min_cll);
+}
+
+static void intel_hdr_output_info(struct drm_printer *p,
+                                 struct drm_connector *connector)
+{
+       const struct drm_connector_state *conn_state = connector->state;
+       const struct intel_crtc_state *crtc_state;
+       const struct hdmi_drm_infoframe *frame;
+
+       if (!conn_state || !conn_state->crtc)
+               return;
+
+       crtc_state = to_intel_crtc_state(conn_state->crtc->state);
+
+       drm_printf_indent(p, 1, "HDR output metadata blob: %s\n",
+                         str_yes_no(conn_state->hdr_output_metadata));
+
+       /*
+        * Both HDMI and DP fill in infoframes.drm, but HDMI transmits it as a
+        * DRM InfoFrame and DP as a gamut metadata SDP, each with its own
+        * enable bit.
+        */
+       if (!(crtc_state->infoframes.enable &
+             (intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM) |
+              intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA)))) {
+               drm_printf_indent(p, 1, "HDR output: off\n");
+               return;
+       }
+
+       frame = &crtc_state->infoframes.drm.drm;
+
+       drm_printf_indent(p, 1, "HDR output: on, EOTF: %s, metadata type: %d\n",
+                         hdmi_eotf_get_name(frame->eotf), 
frame->metadata_type);
+       drm_printf_indent(p, 2, "primaries: r(%u,%u) g(%u,%u) b(%u,%u) 
wp(%u,%u)\n",
+                         frame->display_primaries[0].x, 
frame->display_primaries[0].y,
+                         frame->display_primaries[1].x, 
frame->display_primaries[1].y,
+                         frame->display_primaries[2].x, 
frame->display_primaries[2].y,
+                         frame->white_point.x, frame->white_point.y);
+       drm_printf_indent(p, 2, "mastering luminance: max %u nits, min %u 
(0.0001 nits)\n",
+                         frame->max_display_mastering_luminance,
+                         frame->min_display_mastering_luminance);
+       drm_printf_indent(p, 2, "max_cll: %u nits, max_fall: %u nits\n",
+                         frame->max_cll, frame->max_fall);
+}
+
 static void intel_connector_info(struct seq_file *m,
                                 struct drm_connector *connector)
 {
@@ -264,6 +352,7 @@ static void intel_connector_info(struct seq_file *m,
        seq_printf(m, "\tsubpixel order: %s\n",
                   
drm_get_subpixel_order_name(connector->display_info.subpixel_order));
        seq_printf(m, "\tCEA rev: %d\n", connector->display_info.cea_rev);
+       intel_hdr_sink_info(&p, connector);
 
        switch (connector->connector_type) {
        case DRM_MODE_CONNECTOR_DisplayPort:
@@ -288,6 +377,7 @@ static void intel_connector_info(struct seq_file *m,
        intel_hdcp_info(m, intel_connector);
 
        seq_printf(m, "\tmax bpc: %u\n", connector->display_info.bpc);
+       intel_hdr_output_info(&p, connector);
 
        intel_panel_info(m, intel_connector);
 
-- 
2.53.0

Reply via email to