Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68f1a00c authored by Anthony Koo's avatar Anthony Koo Committed by Alex Deucher
Browse files

drm/amd/display: interface to check if timing can be seamless



[Why]
Need to figure out whether a timing we want to commit matches
something that GOP already programmed, in which case
we can decide to some optimizations

[How]
1. Add way to check for DIG FE
2. Add way to check for matching OTG timing
3. Add way to check for matching pixel clock (if possible)
    - Currently only support DP for pixel clock, since it is easy to calc

Signed-off-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c00800c4
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -969,6 +969,52 @@ static bool context_changed(
	return false;
}

bool dc_validate_seamless_boot_timing(struct dc *dc,
				const struct dc_sink *sink,
				struct dc_crtc_timing *crtc_timing)
{
	struct timing_generator *tg;
	struct dc_link *link = sink->link;
	unsigned int inst;

	/* Check for enabled DIG to identify enabled display */
	if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
		return false;

	/* Check for which front end is used by this encoder.
	 * Note the inst is 1 indexed, where 0 is undefined.
	 * Note that DIG_FE can source from different OTG but our
	 * current implementation always map 1-to-1, so this code makes
	 * the same assumption and doesn't check OTG source.
	 */
	inst = link->link_enc->funcs->get_dig_frontend(link->link_enc) - 1;

	/* Instance should be within the range of the pool */
	if (inst >= dc->res_pool->pipe_count)
		return false;

	tg = dc->res_pool->timing_generators[inst];

	if (!tg->funcs->is_matching_timing)
		return false;

	if (!tg->funcs->is_matching_timing(tg, crtc_timing))
		return false;

	if (dc_is_dp_signal(link->connector_signal)) {
		unsigned int pix_clk_100hz;

		dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
			dc->res_pool->dp_clock_source,
			inst, &pix_clk_100hz);

		if (crtc_timing->pix_clk_100hz != pix_clk_100hz)
			return false;
	}

	return true;
}

bool dc_enable_stereo(
	struct dc *dc,
	struct dc_state *context,
+4 −0
Original line number Diff line number Diff line
@@ -594,6 +594,10 @@ struct dc_validation_set {
	uint8_t plane_count;
};

bool dc_validate_seamless_boot_timing(struct dc *dc,
				const struct dc_sink *sink,
				struct dc_crtc_timing *crtc_timing);

enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state);

void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info);
+26 −2
Original line number Diff line number Diff line
@@ -977,6 +977,28 @@ static bool dce110_clock_source_power_down(
	return bp_result == BP_RESULT_OK;
}

static bool get_pixel_clk_frequency_100hz(
		struct clock_source *clock_source,
		unsigned int inst,
		unsigned int *pixel_clk_khz)
{
	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
	unsigned int clock_hz = 0;

	if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
		clock_hz = REG_READ(PHASE[inst]);

		/* NOTE: There is agreement with VBIOS here that MODULO is
		 * programmed equal to DPREFCLK, in which case PHASE will be
		 * equivalent to pixel clock.
		 */
		*pixel_clk_khz = clock_hz / 100;
		return true;
	}

	return false;
}

/*****************************************/
/* Constructor                           */
/*****************************************/
@@ -984,12 +1006,14 @@ static bool dce110_clock_source_power_down(
static const struct clock_source_funcs dce112_clk_src_funcs = {
	.cs_power_down = dce110_clock_source_power_down,
	.program_pix_clk = dce112_program_pix_clk,
	.get_pix_clk_dividers = dce112_get_pix_clk_dividers
	.get_pix_clk_dividers = dce112_get_pix_clk_dividers,
	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
};
static const struct clock_source_funcs dce110_clk_src_funcs = {
	.cs_power_down = dce110_clock_source_power_down,
	.program_pix_clk = dce110_program_pix_clk,
	.get_pix_clk_dividers = dce110_get_pix_clk_dividers
	.get_pix_clk_dividers = dce110_get_pix_clk_dividers,
	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
};


+10 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ static const struct link_encoder_funcs dcn10_lnk_enc_funcs = {
	.enable_hpd = dcn10_link_encoder_enable_hpd,
	.disable_hpd = dcn10_link_encoder_disable_hpd,
	.is_dig_enabled = dcn10_is_dig_enabled,
	.get_dig_frontend = dcn10_get_dig_frontend,
	.destroy = dcn10_link_encoder_destroy
};

@@ -495,6 +496,15 @@ bool dcn10_is_dig_enabled(struct link_encoder *enc)
	return value;
}

unsigned int dcn10_get_dig_frontend(struct link_encoder *enc)
{
	struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
	uint32_t value;

	REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value);
	return value;
}

static void link_encoder_disable(struct dcn10_link_encoder *enc10)
{
	/* reset training pattern */
+2 −0
Original line number Diff line number Diff line
@@ -336,6 +336,8 @@ void dcn10_psr_program_secondary_packet(struct link_encoder *enc,

bool dcn10_is_dig_enabled(struct link_encoder *enc);

unsigned int dcn10_get_dig_frontend(struct link_encoder *enc);

void dcn10_aux_initialize(struct dcn10_link_encoder *enc10);

#endif /* __DC_LINK_ENCODER__DCN10_H__ */
Loading