Commit ec8e59cb authored by Bhawanpreet Lakha's avatar Bhawanpreet Lakha Committed by Alex Deucher
Browse files

drm/amd/display: Get replay info from VSDB



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: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Reviewed-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 7957ec80
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -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) {
+14 −0
Original line number Diff line number Diff line
@@ -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 {
+7 −0
Original line number Diff line number Diff line
@@ -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;