Commit 2e6c79e4 authored by Jack Chang's avatar Jack Chang Committed by Alex Deucher
Browse files

drm/amd/display: Add panel replay enablement option and logic



[Why&How]
1.Add flow to enable and configure panel replay enablement and
configuration
2.Add registry key for enable option
3.Add replay version check to be compatible with freesync replay
4.Add AC/DC switch function to notify ac/dc change.
5.Add flow in set event function to check and decide Replay
enable/disable

Reviewed-by: default avatarRobin Chen <robin.chen@amd.com>
Signed-off-by: default avatarJack Chang <jack.chang@amd.com>
Signed-off-by: default avatarLeon Huang <Leon.Huang1@amd.com>
Signed-off-by: default avatarIvan Lipski <ivan.lipski@amd.com>
Tested-by: default avatarDan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ddc6b22d
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -1346,6 +1346,31 @@ union dpcd_replay_configuration {
	unsigned char raw;
};

union panel_replay_enable_and_configuration_1 {
	struct {
		unsigned char PANEL_REPLAY_ENABLE                     :1;
		unsigned char PANEL_REPLAY_CRC_ENABLE                 :1;
		unsigned char IRQ_HPD_ASSDP_MISSING                   :1;
		unsigned char IRQ_HPD_VSCSDP_UNCORRECTABLE_ERROR      :1;
		unsigned char IRQ_HPD_RFB_ERROR                       :1;
		unsigned char IRQ_HPD_ACTIVE_FRAME_CRC_ERROR          :1;
		unsigned char PANEL_REPLAY_SELECTIVE_UPDATE_ENABLE    :1;
		unsigned char PANEL_REPLAY_EARLY_TRANSPORT_ENABLE     :1;
	} bits;
	unsigned char raw;
};

union panel_replay_enable_and_configuration_2 {
	struct {
		unsigned char SINK_REFRESH_RATE_UNLOCK_GRANTED        :1;
		unsigned char RESERVED                                :1;
		unsigned char SU_Y_GRANULARITY_EXT_VALUE_ENABLED      :1;
		unsigned char SU_Y_GRANULARITY_EXT_VALUE              :4;
		unsigned char SU_REGION_SCAN_LINE_CAPTURE_INDICATION  :1;
	} bits;
	unsigned char raw;
};

union dpcd_alpm_configuration {
	struct {
		unsigned char ENABLE                    : 1;
+124 −2
Original line number Diff line number Diff line
@@ -984,7 +984,117 @@ bool edp_get_replay_state(const struct dc_link *link, uint64_t *state)
	return true;
}

bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream)
static bool edp_setup_panel_replay(struct dc_link *link, const struct dc_stream_state *stream)
{
	/* To-do: Setup Replay */
	struct dc *dc;
	struct dmub_replay *replay;
	int i;
	unsigned int panel_inst;
	struct replay_context replay_context = { 0 };
	unsigned int lineTimeInNs = 0;

	union panel_replay_enable_and_configuration_1 pr_config_1 = { 0 };
	union panel_replay_enable_and_configuration_2 pr_config_2 = { 0 };

	union dpcd_alpm_configuration alpm_config;

	replay_context.controllerId = CONTROLLER_ID_UNDEFINED;

	if (!link)
		return false;

	//Clear Panel Replay enable & config
	dm_helpers_dp_write_dpcd(link->ctx, link,
		DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1,
		(uint8_t *)&(pr_config_1.raw), sizeof(uint8_t));

	dm_helpers_dp_write_dpcd(link->ctx, link,
		DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2,
		(uint8_t *)&(pr_config_2.raw), sizeof(uint8_t));

	if (!(link->replay_settings.config.replay_supported))
		return false;

	dc = link->ctx->dc;

	//not sure should keep or not
	replay = dc->res_pool->replay;

	if (!replay)
		return false;

	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
		return false;

	replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel;
	replay_context.digbe_inst = link->link_enc->transmitter;
	replay_context.digfe_inst = link->link_enc->preferred_engine;

	for (i = 0; i < MAX_PIPES; i++) {
		if (dc->current_state->res_ctx.pipe_ctx[i].stream
				== stream) {
			/* dmcu -1 for all controller id values,
			 * therefore +1 here
			 */
			replay_context.controllerId =
				dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst + 1;
			break;
		}
	}

	lineTimeInNs =
		((stream->timing.h_total * 1000000) /
			(stream->timing.pix_clk_100hz / 10)) + 1;

	replay_context.line_time_in_ns = lineTimeInNs;

	link->replay_settings.replay_feature_enabled =
			replay->funcs->replay_copy_settings(replay, link, &replay_context, panel_inst);

	if (link->replay_settings.replay_feature_enabled) {
		pr_config_1.bits.PANEL_REPLAY_ENABLE = 1;
		pr_config_1.bits.PANEL_REPLAY_CRC_ENABLE = 1;
		pr_config_1.bits.IRQ_HPD_ASSDP_MISSING = 1;
		pr_config_1.bits.IRQ_HPD_VSCSDP_UNCORRECTABLE_ERROR = 1;
		pr_config_1.bits.IRQ_HPD_RFB_ERROR = 1;
		pr_config_1.bits.IRQ_HPD_ACTIVE_FRAME_CRC_ERROR = 1;
		pr_config_1.bits.PANEL_REPLAY_SELECTIVE_UPDATE_ENABLE = 1;
		pr_config_1.bits.PANEL_REPLAY_EARLY_TRANSPORT_ENABLE = 1;

		pr_config_2.bits.SINK_REFRESH_RATE_UNLOCK_GRANTED = 0;
		pr_config_2.bits.SU_Y_GRANULARITY_EXT_VALUE_ENABLED = 0;
		pr_config_2.bits.SU_REGION_SCAN_LINE_CAPTURE_INDICATION = 0;

		dm_helpers_dp_write_dpcd(link->ctx, link,
			DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1,
			(uint8_t *)&(pr_config_1.raw), sizeof(uint8_t));

		dm_helpers_dp_write_dpcd(link->ctx, link,
			DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2,
			(uint8_t *)&(pr_config_2.raw), sizeof(uint8_t));

		//ALPM Setup
		memset(&alpm_config, 0, sizeof(alpm_config));
		alpm_config.bits.ENABLE = link->replay_settings.config.alpm_mode != DC_ALPM_UNSUPPORTED ? 1 : 0;

		if (link->replay_settings.config.alpm_mode == DC_ALPM_AUXLESS) {
			alpm_config.bits.ALPM_MODE_SEL = 1;
			alpm_config.bits.ACDS_PERIOD_DURATION = 1;
		}

		dm_helpers_dp_write_dpcd(
			link->ctx,
			link,
			DP_RECEIVER_ALPM_CONFIG,
			&alpm_config.raw,
			sizeof(alpm_config.raw));
	}

	return true;
}

static bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_state *stream)
{
	/* To-do: Setup Replay */
	struct dc *dc;
@@ -1080,6 +1190,18 @@ bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream
	return true;
}

bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream)
{
	if (!link)
		return false;
	if (link->replay_settings.config.replay_version == DC_VESA_PANEL_REPLAY)
		return edp_setup_panel_replay(link, stream);
	else if (link->replay_settings.config.replay_version == DC_FREESYNC_REPLAY)
		return edp_setup_freesync_replay(link, stream);
	else
		return false;
}

/*
 * This is general Interface for Replay to set an 32 bit variable to dmub
 * replay_FW_Message_type: Indicates which instruction or variable pass to DMUB
+16 −0
Original line number Diff line number Diff line
@@ -30,6 +30,22 @@
#ifndef DP_SINK_HW_REVISION_START // can remove this once the define gets into linux drm_dp_helper.h
#define DP_SINK_HW_REVISION_START 0x409
#endif
/* Panel Replay*/
#ifndef DP_PANEL_REPLAY_CAPABILITY_SUPPORT // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PANEL_REPLAY_CAPABILITY_SUPPORT 0x0b0
#endif /* DP_PANEL_REPLAY_CAPABILITY_SUPPORT */
#ifndef DP_PANEL_REPLAY_CAPABILITY // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PANEL_REPLAY_CAPABILITY 0x0b1
#endif /* DP_PANEL_REPLAY_CAPABILITY */
#ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1  // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1  0x1b0
#endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 */
#ifndef DP_PANEL_REPLAY_ENABLE // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PANEL_REPLAY_ENABLE (1 << 0)
#endif /* DP_PANEL_REPLAY_ENABLE */
#ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 0x1b1
#endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 */

enum dpcd_revision {
	DPCD_REV_10 = 0x10,
+3 −0
Original line number Diff line number Diff line
@@ -1037,6 +1037,9 @@ void calculate_replay_link_off_frame_count(struct dc_link *link,
	uint8_t max_link_off_frame_count = 0;
	uint16_t max_deviation_line = 0,  pixel_deviation_per_line = 0;

	if (!link || link->replay_settings.config.replay_version != DC_FREESYNC_REPLAY)
		return;

	max_deviation_line = link->dpcd_caps.pr_info.max_deviation_line;
	pixel_deviation_per_line = link->dpcd_caps.pr_info.pixel_deviation_per_line;