Commit 77a2b726 authored by Vladimir Stempen's avatar Vladimir Stempen Committed by Alex Deucher
Browse files

drm/amd/display: Synchronize displays with different timings



[why]
 Vendor based fan noise improvement

[how]
Report timing synchronizable when DP streams time frame
difference is less than 0.05 percent. Adjust DP  DTOs and
sync displays using  MASTER_UPDATE_LOCK_DB_X_Y

Signed-off-by: default avatarVladimir Stempen <vladimir.stempen@amd.com>
Acked-by: default avatarBindu Ramamurthy <bindu.r@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 860b0cf5
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
@@ -1102,6 +1102,7 @@ static void program_timing_sync(

	for (i = 0; i < pipe_count; i++) {
		int group_size = 1;
		enum timing_synchronization_type sync_type = NOT_SYNCHRONIZABLE;
		struct pipe_ctx *pipe_set[MAX_PIPES];

		if (!unsynced_pipes[i])
@@ -1116,10 +1117,22 @@ static void program_timing_sync(
		for (j = i + 1; j < pipe_count; j++) {
			if (!unsynced_pipes[j])
				continue;

			if (resource_are_streams_timing_synchronizable(
			if (sync_type != TIMING_SYNCHRONIZABLE &&
				dc->hwss.enable_vblanks_synchronization &&
				unsynced_pipes[j]->stream_res.tg->funcs->align_vblanks &&
				resource_are_vblanks_synchronizable(
					unsynced_pipes[j]->stream,
					pipe_set[0]->stream)) {
				sync_type = VBLANK_SYNCHRONIZABLE;
				pipe_set[group_size] = unsynced_pipes[j];
				unsynced_pipes[j] = NULL;
				group_size++;
			} else
			if (sync_type != VBLANK_SYNCHRONIZABLE &&
				resource_are_streams_timing_synchronizable(
					unsynced_pipes[j]->stream,
					pipe_set[0]->stream)) {
				sync_type = TIMING_SYNCHRONIZABLE;
				pipe_set[group_size] = unsynced_pipes[j];
				unsynced_pipes[j] = NULL;
				group_size++;
@@ -1145,7 +1158,6 @@ static void program_timing_sync(
			}
		}


		for (k = 0; k < group_size; k++) {
			struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);

@@ -1175,8 +1187,14 @@ static void program_timing_sync(
		}

		if (group_size > 1) {
			if (sync_type == TIMING_SYNCHRONIZABLE) {
				dc->hwss.enable_timing_synchronization(
					dc, group_index, group_size, pipe_set);
			} else
				if (sync_type == VBLANK_SYNCHRONIZABLE) {
				dc->hwss.enable_vblanks_synchronization(
					dc, group_index, group_size, pipe_set);
				}
			group_index++;
		}
		num_group++;
+43 −0
Original line number Diff line number Diff line
@@ -417,6 +417,49 @@ int resource_get_clock_source_reference(
	return -1;
}

bool resource_are_vblanks_synchronizable(
	struct dc_stream_state *stream1,
	struct dc_stream_state *stream2)
{
	uint32_t base60_refresh_rates[] = {10, 20, 5};
	uint8_t i;
	uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]);
	int64_t frame_time_diff;

	if (stream1->ctx->dc->config.vblank_alignment_dto_params &&
		stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&
		dc_is_dp_signal(stream1->signal) &&
		dc_is_dp_signal(stream2->signal) &&
		false == stream1->has_non_synchronizable_pclk &&
		false == stream2->has_non_synchronizable_pclk &&
		stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&
		stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {
		/* disable refresh rates higher than 60Hz for now */
		if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/
				stream1->timing.v_total > 60)
			return false;
		if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/
				stream2->timing.v_total > 60)
			return false;
		frame_time_diff = (int64_t)10000 *
			stream1->timing.h_total *
			stream1->timing.v_total *
			stream2->timing.pix_clk_100hz /
			stream1->timing.pix_clk_100hz /
			stream2->timing.h_total /
			stream2->timing.v_total;
		for (i = 0; i < rr_count; i++) {
			int64_t diff = (frame_time_diff * base60_refresh_rates[i]) / 10 - 10000;

			if (diff < 0)
				diff = -diff;
			if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)
				return true;
		}
	}
	return false;
}

bool resource_are_streams_timing_synchronizable(
	struct dc_stream_state *stream1,
	struct dc_stream_state *stream2)
+3 −0
Original line number Diff line number Diff line
@@ -301,6 +301,8 @@ struct dc_config {
#if defined(CONFIG_DRM_AMD_DC_DCN)
	bool clamp_min_dcfclk;
#endif
	uint64_t vblank_alignment_dto_params;
	uint8_t  vblank_alignment_max_frame_time_diff;
};

enum visual_confirm {
@@ -528,6 +530,7 @@ struct dc_debug_options {
	bool disable_dsc;
	bool enable_dram_clock_change_one_display_vactive;
	union mem_low_power_enable_options enable_mem_low_power;
	bool force_vblank_alignment;
};

struct dc_debug_data {
+1 −0
Original line number Diff line number Diff line
@@ -705,6 +705,7 @@ struct dc_crtc_timing_flags {
#ifndef TRIM_FSFT
	uint32_t FAST_TRANSPORT: 1;
#endif
	uint32_t VBLANK_SYNCHRONIZABLE: 1;
};

enum dc_timing_3d_format {
+3 −0
Original line number Diff line number Diff line
@@ -228,6 +228,9 @@ struct dc_stream_state {
	uint32_t stream_id;
	bool is_dsc_enabled;
	union stream_update_flags update_flags;

	bool has_non_synchronizable_pclk;
	bool vblank_synchronized;
};

#define ABM_LEVEL_IMMEDIATE_DISABLE 255
Loading