Commit f57fa0f2 authored by Leo Chen's avatar Leo Chen Committed by Alex Deucher
Browse files

drm/amd/display: Add symclk workaround during disable link output



[Why & How]
This is originally a change (9c75891f) in DCN32 because of the lack
of interface to set TX while keeping symclk on. Adding this workaround
to DCN314 will resolve the current issue.

Fixes: 9c75891f ("drm/amd/display: rework recent update PHY state commit")
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: default avatarAlex Hung <alex.hung@amd.com>
Signed-off-by: default avatarLeo Chen <sancchen@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 58d9b9a1
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -423,3 +423,68 @@ void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool

	PERF_TRACE();
}
static void apply_symclk_on_tx_off_wa(struct dc_link *link)
{
	/* There are use cases where SYMCLK is referenced by OTG. For instance
	 * for TMDS signal, OTG relies SYMCLK even if TX video output is off.
	 * However current link interface will power off PHY when disabling link
	 * output. This will turn off SYMCLK generated by PHY. The workaround is
	 * to identify such case where SYMCLK is still in use by OTG when we
	 * power off PHY. When this is detected, we will temporarily power PHY
	 * back on and move PHY's SYMCLK state to SYMCLK_ON_TX_OFF by calling
	 * program_pix_clk interface. When OTG is disabled, we will then power
	 * off PHY by calling disable link output again.
	 *
	 * In future dcn generations, we plan to rework transmitter control
	 * interface so that we could have an option to set SYMCLK ON TX OFF
	 * state in one step without this workaround
	 */

	struct dc *dc = link->ctx->dc;
	struct pipe_ctx *pipe_ctx = NULL;
	uint8_t i;

	if (link->phy_state.symclk_ref_cnts.otg > 0) {
		for (i = 0; i < MAX_PIPES; i++) {
			pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
			if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) {
				pipe_ctx->clock_source->funcs->program_pix_clk(
						pipe_ctx->clock_source,
						&pipe_ctx->stream_res.pix_clk_params,
						dc->link_srv->dp_get_encoding_format(
								&pipe_ctx->link_config.dp_link_settings),
						&pipe_ctx->pll_settings);
				link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
				break;
			}
		}
	}
}

void dcn314_disable_link_output(struct dc_link *link,
		const struct link_resource *link_res,
		enum signal_type signal)
{
	struct dc *dc = link->ctx->dc;
	const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
	struct dmcu *dmcu = dc->res_pool->dmcu;

	if (signal == SIGNAL_TYPE_EDP &&
			link->dc->hwss.edp_backlight_control)
		link->dc->hwss.edp_backlight_control(link, false);
	else if (dmcu != NULL && dmcu->funcs->lock_phy)
		dmcu->funcs->lock_phy(dmcu);

	link_hwss->disable_link_output(link, link_res, signal);
	link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
	/*
	 * Add the logic to extract BOTH power up and power down sequences
	 * from enable/disable link output and only call edp panel control
	 * in enable_link_dp and disable_link_dp once.
	 */
	if (dmcu != NULL && dmcu->funcs->lock_phy)
		dmcu->funcs->unlock_phy(dmcu);
	dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);

	apply_symclk_on_tx_off_wa(link);
}
+2 −0
Original line number Diff line number Diff line
@@ -45,4 +45,6 @@ void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool

void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on);

void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal);

#endif /* __DC_HWSS_DCN314_H__ */
+1 −1
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
	.enable_lvds_link_output = dce110_enable_lvds_link_output,
	.enable_tmds_link_output = dce110_enable_tmds_link_output,
	.enable_dp_link_output = dce110_enable_dp_link_output,
	.disable_link_output = dce110_disable_link_output,
	.disable_link_output = dcn314_disable_link_output,
	.z10_restore = dcn31_z10_restore,
	.z10_save_init = dcn31_z10_save_init,
	.set_disp_pattern_generator = dcn30_set_disp_pattern_generator,