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@xxxxxxx> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 +++++++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 14 +++++++ .../amd/display/amdgpu_dm/amdgpu_dm_replay.c | 11 +++--- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a6551c049cc1..d74d5ba39d92 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10546,6 +10546,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; + 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) { @@ -10681,6 +10716,8 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, freesync_capable = true; } } + parse_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); + } 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) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 4561f55afa99..5c9cf6c147d7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -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; @@ -604,6 +613,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 { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c index 7690ab6125a1..f82575e09848 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c @@ -46,11 +46,8 @@ static bool link_supports_replay(struct dc_link *link, struct amdgpu_dm_connecto if (!state->freesync_capable) return false; - //TODO VSDB replay check - /* i = parse_amd_vsdb(aconnector, edid, &vsdb_info); */ - - /* if(!vsdb_info.replay_mode) */ - /* return false; */ + if (!aconnector->vsdb_info.replay_mode) + return false; // Check the eDP version if (dpcd_caps->edp_rev < EDP_REVISION_13) @@ -77,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; -- 2.25.1