drm/amd/display: Get replay info from VSDB
authorBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Mon, 12 Jun 2023 18:06:39 +0000 (14:06 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 9 Aug 2023 13:46:04 +0000 (09:46 -0400)
We need to make sure that the panel supports replay.

This info is inside the amd vsdb (vendor specific data block). Create a
function to parse the block and read the replay_mode bit.

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c

index ae83275b6d5fc9e640e7b99a19042f33cce92cd9..4d3d6009838c7e4685ddbd9b655f002714a6db36 100644 (file)
@@ -10490,6 +10490,41 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
        return ret;
 }
 
+static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
+                         struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
+{
+       u8 *edid_ext = NULL;
+       int i;
+       int j = 0;
+
+       if (edid == NULL || edid->extensions == 0)
+               return -ENODEV;
+
+       /* Find DisplayID extension */
+       for (i = 0; i < edid->extensions; i++) {
+               edid_ext = (void *)(edid + (i + 1));
+               if (edid_ext[0] == DISPLAYID_EXT)
+                       break;
+       }
+
+       while (j < EDID_LENGTH) {
+               struct amd_vsdb_block *amd_vsdb = (struct amd_vsdb_block *)&edid_ext[j];
+               unsigned int ieeeId = (amd_vsdb->ieee_id[2] << 16) | (amd_vsdb->ieee_id[1] << 8) | (amd_vsdb->ieee_id[0]);
+
+               if (ieeeId == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID &&
+                               amd_vsdb->version == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3) {
+                       vsdb_info->replay_mode = (amd_vsdb->feature_caps & AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE) ? true : false;
+                       vsdb_info->amd_vsdb_version = HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3;
+                       DRM_DEBUG_KMS("Panel supports Replay Mode: %d\n", vsdb_info->replay_mode);
+
+                       return true;
+               }
+               j++;
+       }
+
+       return false;
+}
+
 static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
                struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
@@ -10625,6 +10660,14 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
                                freesync_capable = true;
                        }
                }
+               parse_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
+
+               if (vsdb_info.replay_mode) {
+                       amdgpu_dm_connector->vsdb_info.replay_mode = vsdb_info.replay_mode;
+                       amdgpu_dm_connector->vsdb_info.amd_vsdb_version = vsdb_info.amd_vsdb_version;
+                       amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP;
+               }
+
        } else if (edid && sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) {
                i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
                if (i >= 0 && vsdb_info.freesync_supported) {
index 9fb5bb3a75a777b619b41eb36ff74d461a3dbee3..a2d34be82613c5614f1b6cecb3f987121ae0afd0 100644 (file)
@@ -51,6 +51,9 @@
 
 #define AMDGPU_DMUB_NOTIFICATION_MAX 5
 
+#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
+#define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
+#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3
 /*
 #include "include/amdgpu_dal_power_if.h"
 #include "amdgpu_dm_irq.h"
@@ -75,6 +78,12 @@ struct dmub_srv;
 struct dc_plane_state;
 struct dmub_notification;
 
+struct amd_vsdb_block {
+       unsigned char ieee_id[3];
+       unsigned char version;
+       unsigned char feature_caps;
+};
+
 struct common_irq_params {
        struct amdgpu_device *adev;
        enum dc_irq_source irq_src;
@@ -609,6 +618,11 @@ struct amdgpu_hdmi_vsdb_info {
         * @max_refresh_rate_hz: FreeSync Maximum Refresh Rate in Hz
         */
        unsigned int max_refresh_rate_hz;
+
+       /**
+        * @replay mode: Replay supported
+        */
+       bool replay_mode;
 };
 
 struct amdgpu_dm_connector {
index b3e14997b4707362c25a3befd950ae772882e4bd..32d3086c4cb7b58e71a5c5697c2c4a85e6ad75da 100644 (file)
@@ -46,6 +46,9 @@ static bool link_supports_replay(struct dc_link *link, struct amdgpu_dm_connecto
        if (!state->freesync_capable)
                return false;
 
+       if (!aconnector->vsdb_info.replay_mode)
+               return false;
+
        // Check the eDP version
        if (dpcd_caps->edp_rev < EDP_REVISION_13)
                return false;
@@ -71,6 +74,10 @@ bool amdgpu_dm_setup_replay(struct dc_link *link, struct amdgpu_dm_connector *ac
        struct replay_config pr_config;
        union replay_debug_flags *debug_flags = NULL;
 
+       // For eDP, if Replay is supported, return true to skip checks
+       if (link->replay_settings.config.replay_supported)
+               return true;
+
        if (!dc_is_embedded_signal(link->connector_signal))
                return false;