Adds a struct to hold HDMI VRR information. `supported` here is an
additional property which allows easier parsing in consumers and adds a
bit of logic used by most driver to decide if VRR is worthwhile.

Additionally, edid-decode seems to throw errors if VRRmin is above 48 Hz
and VRRmax is below 100 Hz. I'm not sure if it's based on an actual HDMI
spec or, again, is showing "best practices".

Signed-off-by: Tomasz Pakuła <[email protected]>
Tested-by: Bernhard Berger <[email protected]>
---
 drivers/gpu/drm/drm_edid.c  | 19 +++++++++++++++++--
 include/drm/drm_connector.h | 20 ++++++++++++++++++++
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index bb6cee249749..981b3b28c94b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6149,6 +6149,19 @@ static void drm_parse_ycbcr420_deep_color_info(struct 
drm_connector *connector,
        hdmi->y420_dc_modes = dc_mask;
 }
 
+static void drm_parse_vrr_info(struct drm_connector *connector, const u8 *db)
+{
+       struct drm_hdmi_vrr_cap *vrr = &connector->display_info.hdmi.vrr_cap;
+
+       vrr->supported = false;
+       if (!(cea_db_payload_len(db) >= 10) || !db[9] || !db[10])
+               return;
+
+       vrr->min_hz = db[9] & DRM_EDID_VRR_MIN_MASK;
+       vrr->max_hz = (db[9] & DRM_EDID_VRR_MAX_UPPER_MASK) << 2 | db[10];
+       vrr->supported = (vrr->min_hz > 0) && (vrr->max_hz - vrr->min_hz > 10);
+}
+
 static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc,
                               const u8 *hf_scds)
 {
@@ -6277,6 +6290,7 @@ static void drm_parse_hdmi_forum_scds(struct 
drm_connector *connector,
        if (cea_db_payload_len(hf_scds) >= 8 && hf_scds[8])
                hdmi->allm_supported = hf_scds[8] & DRM_EDID_ALLM;
 
+       drm_parse_vrr_info(connector, hf_scds);
        if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) {
                drm_parse_dsc_info(hdmi_dsc, hf_scds);
                dsc_support = true;
@@ -6287,8 +6301,9 @@ static void drm_parse_hdmi_forum_scds(struct 
drm_connector *connector,
                    connector->base.id, connector->name,
                    max_tmds_clock, str_yes_no(max_frl_rate), 
str_yes_no(dsc_support));
        drm_dbg_kms(connector->dev,
-               "[CONNECTOR:%d:%s] ALLM support: %s\n",
-               connector->base.id, connector->name, 
str_yes_no(hdmi->allm_supported));
+               "[CONNECTOR:%d:%s] ALLM support: %s, VRR support: %s, VRR min 
Hz: %u, VRR max Hz: %u\n",
+               connector->base.id, connector->name, 
str_yes_no(hdmi->allm_supported),
+               str_yes_no(hdmi->vrr_cap.supported), hdmi->vrr_cap.min_hz, 
hdmi->vrr_cap.max_hz);
 }
 
 static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index ac84884a96a5..8663daccf1db 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -254,6 +254,23 @@ struct drm_scdc {
        struct drm_scrambling scrambling;
 };
 
+/**
+ * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a HDMI sink
+ *
+ * Describes the VRR support provided by HDMI 2.1 sink. The information is
+ * fetched fom additional HFVSDB blocks defined for HDMI 2.1.
+ */
+struct drm_hdmi_vrr_cap {
+       /** @supported: flag for vrr support by sink */
+       bool supported;
+
+       /** @min_hz : minimum supported variable refresh rate */
+       u16 min_hz;
+
+       /** @max_hz : maximum supported variable refresh rate */
+       u16 max_hz;
+};
+
 /**
  * struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink
  *
@@ -333,6 +350,9 @@ struct drm_hdmi_info {
        /** @allm_supported: flag for auto low latency mode support by sink */
        bool allm_supported;
 
+       /** @vrr_cap: VRR capabilities of the sink */
+       struct drm_hdmi_vrr_cap vrr_cap;
+
        /** @dsc_cap: DSC capabilities of the sink */
        struct drm_hdmi_dsc_cap dsc_cap;
 };
-- 
2.52.0

Reply via email to