Commit 5ec43eda authored by Martin Leung's avatar Martin Leung Committed by Alex Deucher
Browse files

drm/amd/display: enabling seamless boot sequence for dcn2



[Why]
Seamless boot (building SW state inheriting BIOS-initialized timing) was
enabled on DCN2, including fixes

[How]
Includes fixes for MPC, DPPCLK, and DIG FE mapping/OTG source select/
Pixel clock.

This is part 2 of 2 for seamless boot NV10

Signed-off-by: default avatarMartin Leung <martin.leung@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 39bdac36
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -960,7 +960,7 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
{
	struct timing_generator *tg;
	struct dc_link *link = sink->link;
	unsigned int inst;
	unsigned int enc_inst, tg_inst;

	/* Check for enabled DIG to identify enabled display */
	if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
@@ -972,13 +972,22 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
	 * 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;
	enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);

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

	tg = dc->res_pool->timing_generators[inst];
	if (enc_inst >= dc->res_pool->stream_enc_count)
		return false;

	tg_inst = dc->res_pool->stream_enc[enc_inst]->funcs->dig_source_otg(
		dc->res_pool->stream_enc[enc_inst]);

	if (tg_inst >= dc->res_pool->timing_generator_count)
		return false;

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

	if (!tg->funcs->is_matching_timing)
		return false;
@@ -991,10 +1000,11 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,

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

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

	}

	return true;
@@ -1904,13 +1914,17 @@ static void commit_planes_do_stream_update(struct dc *dc,

			if (stream_update->dpms_off) {
				dc->hwss.pipe_control_lock(dc, pipe_ctx, true);

				if (*stream_update->dpms_off) {
					core_link_disable_stream(pipe_ctx, KEEP_ACQUIRED_RESOURCE);
					dc->hwss.optimize_bandwidth(dc, dc->current_state);
				} else {
					if (!dc->optimize_seamless_boot)
						dc->hwss.prepare_bandwidth(dc, dc->current_state);

					core_link_enable_stream(dc->current_state, pipe_ctx);
				}

				dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
			}

+12 −1
Original line number Diff line number Diff line
@@ -1421,6 +1421,16 @@ static enum dc_status enable_link_dp(
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
	bool fec_enable;
#endif
	int i;
	bool apply_seamless_boot_optimization = false;

	// check for seamless boot
	for (i = 0; i < state->stream_count; i++) {
		if (state->streams[i]->apply_seamless_boot_optimization) {
			apply_seamless_boot_optimization = true;
			break;
		}
	}

	/* get link settings for video mode timing */
	decide_link_settings(stream, &link_settings);
@@ -1442,6 +1452,7 @@ static enum dc_status enable_link_dp(

	pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =
			link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
	if (!apply_seamless_boot_optimization)
		state->clk_mgr->funcs->update_clocks(state->clk_mgr, state, false);

	dp_enable_link_phy(
+24 −15
Original line number Diff line number Diff line
@@ -1893,7 +1893,7 @@ static int acquire_resource_from_hw_enabled_state(
		struct dc_stream_state *stream)
{
	struct dc_link *link = stream->link;
	unsigned int inst;
	unsigned int inst, tg_inst;

	/* Check for enabled DIG to identify enabled display */
	if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
@@ -1905,28 +1905,37 @@ static int acquire_resource_from_hw_enabled_state(
	 * 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;
	inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);

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

	if (!res_ctx->pipe_ctx[inst].stream) {
		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[inst];
	if (inst >= pool->stream_enc_count)
		return -1;

	tg_inst = pool->stream_enc[inst]->funcs->dig_source_otg(pool->stream_enc[inst]);

	if (tg_inst >= pool->timing_generator_count)
		return false;

	if (!res_ctx->pipe_ctx[tg_inst].stream) {
		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst];

		pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
		pipe_ctx->plane_res.mi = pool->mis[tg_inst];
		pipe_ctx->plane_res.hubp = pool->hubps[tg_inst];
		pipe_ctx->plane_res.ipp = pool->ipps[tg_inst];
		pipe_ctx->plane_res.xfm = pool->transforms[tg_inst];
		pipe_ctx->plane_res.dpp = pool->dpps[tg_inst];
		pipe_ctx->stream_res.opp = pool->opps[tg_inst];

		pipe_ctx->stream_res.tg = pool->timing_generators[inst];
		pipe_ctx->plane_res.mi = pool->mis[inst];
		pipe_ctx->plane_res.hubp = pool->hubps[inst];
		pipe_ctx->plane_res.ipp = pool->ipps[inst];
		pipe_ctx->plane_res.xfm = pool->transforms[inst];
		pipe_ctx->plane_res.dpp = pool->dpps[inst];
		pipe_ctx->stream_res.opp = pool->opps[inst];
		if (pool->dpps[inst])
			pipe_ctx->plane_res.mpcc_inst = pool->dpps[inst]->inst;
		pipe_ctx->pipe_idx = inst;
		if (pool->dpps[tg_inst])
			pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst;
		pipe_ctx->pipe_idx = tg_inst;

		pipe_ctx->stream = stream;
		return inst;
		return tg_inst;
	}

	return -1;
+2 −1
Original line number Diff line number Diff line
@@ -1061,7 +1061,8 @@ static bool dcn20_program_pix_clk(
static const struct clock_source_funcs dcn20_clk_src_funcs = {
	.cs_power_down = dce110_clock_source_power_down,
	.program_pix_clk = dcn20_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
};
#endif

+12 −0
Original line number Diff line number Diff line
@@ -1602,6 +1602,17 @@ static void dig_connect_to_otg(
	REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst);
}

static unsigned int dig_source_otg(
	struct stream_encoder *enc)
{
	uint32_t tg_inst = 0;
	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);

	REG_GET(DIG_FE_CNTL, DIG_SOURCE_SELECT, &tg_inst);

	return tg_inst;
}

static const struct stream_encoder_funcs dce110_str_enc_funcs = {
	.dp_set_stream_attribute =
		dce110_stream_encoder_dp_set_stream_attribute,
@@ -1637,6 +1648,7 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = {
	.set_avmute = dce110_stream_encoder_set_avmute,
	.dig_connect_to_otg  = dig_connect_to_otg,
	.hdmi_reset_stream_attribute = dce110_reset_hdmi_stream_attribute,
	.dig_source_otg = dig_source_otg,
};

void dce110_stream_encoder_construct(
Loading