drm/amd/display: Fix refresh rate range for some panel
authorjsg <jsg@openbsd.org>
Fri, 26 Jul 2024 03:39:34 +0000 (03:39 +0000)
committerjsg <jsg@openbsd.org>
Fri, 26 Jul 2024 03:39:34 +0000 (03:39 +0000)
From Tom Chung
607731f315d15558696e9b542121d40411df37fd in linux-6.6.y/6.6.42
9ef1548aeaa8858e7aee2152bf95cc71cdcd6dff in mainline linux

sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index 43cd301..cf5afb4 100644 (file)
@@ -10637,6 +10637,49 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
        return ret;
 }
 
+static void parse_edid_displayid_vrr(struct drm_connector *connector,
+               struct edid *edid)
+{
+       u8 *edid_ext = NULL;
+       int i;
+       int j = 0;
+       u16 min_vfreq;
+       u16 max_vfreq;
+
+       if (edid == NULL || edid->extensions == 0)
+               return;
+
+       /* Find DisplayID extension */
+       for (i = 0; i < edid->extensions; i++) {
+               edid_ext = (void *)(edid + (i + 1));
+               if (edid_ext[0] == DISPLAYID_EXT)
+                       break;
+       }
+
+       if (edid_ext == NULL)
+               return;
+
+       while (j < EDID_LENGTH) {
+               /* Get dynamic video timing range from DisplayID if available */
+               if (EDID_LENGTH - j > 13 && edid_ext[j] == 0x25 &&
+                   (edid_ext[j+1] & 0xFE) == 0 && (edid_ext[j+2] == 9)) {
+                       min_vfreq = edid_ext[j+9];
+                       if (edid_ext[j+1] & 7)
+                               max_vfreq = edid_ext[j+10] + ((edid_ext[j+11] & 3) << 8);
+                       else
+                               max_vfreq = edid_ext[j+10];
+
+                       if (max_vfreq && min_vfreq) {
+                               connector->display_info.monitor_range.max_vfreq = max_vfreq;
+                               connector->display_info.monitor_range.min_vfreq = min_vfreq;
+
+                               return;
+                       }
+               }
+               j++;
+       }
+}
+
 static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
                          struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
@@ -10759,6 +10802,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
        if (!adev->dm.freesync_module)
                goto update;
 
+       /* Some eDP panels only have the refresh rate range info in DisplayID */
+       if ((connector->display_info.monitor_range.min_vfreq == 0 ||
+            connector->display_info.monitor_range.max_vfreq == 0))
+               parse_edid_displayid_vrr(connector, edid);
+
        if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT ||
                     sink->sink_signal == SIGNAL_TYPE_EDP)) {
                bool edid_check_required = false;