Commit 1ef893e2 authored by Yongqiang Sun's avatar Yongqiang Sun Committed by Alex Deucher

drm/amd/display: workaround for HDMI hotplug in DPMSOFF state

[Why]
When hotplug a HDMI monitor during entering S0i3 or DPMSOFF state due to
entering infinite loop when calling vbios to program pixel clocks. In
this scenario, pll is enabled but phy is not, and there is not a
programing guide for this case.

[How]
Before we having the proper programing guide, before disable pll, doing
a phy enable and disable to avoid the issue.
Signed-off-by: default avatarYongqiang Sun <yongqiang.sun@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b45f9a3e
...@@ -654,6 +654,9 @@ enum dc_status dcn20_enable_stream_timing( ...@@ -654,6 +654,9 @@ enum dc_status dcn20_enable_stream_timing(
return DC_ERROR_UNEXPECTED; return DC_ERROR_UNEXPECTED;
} }
if (dc->hwseq->funcs.PLAT_58856_wa && (!dc_is_dp_signal(stream->signal)))
dc->hwseq->funcs.PLAT_58856_wa(context, pipe_ctx);
pipe_ctx->stream_res.tg->funcs->program_timing( pipe_ctx->stream_res.tg->funcs->program_timing(
pipe_ctx->stream_res.tg, pipe_ctx->stream_res.tg,
&stream->timing, &stream->timing,
......
...@@ -112,3 +112,25 @@ void dcn21_optimize_pwr_state( ...@@ -112,3 +112,25 @@ void dcn21_optimize_pwr_state(
true); true);
} }
/* If user hotplug a HDMI monitor while in monitor off,
* OS will do a mode set (with output timing) but keep output off.
* In this case DAL will ask vbios to power up the pll in the PHY.
* If user unplug the monitor (while we are on monitor off) or
* system attempt to enter modern standby (which we will disable PLL),
* PHY will hang on the next mode set attempt.
* if enable PLL follow by disable PLL (without executing lane enable/disable),
* RDPCS_PHY_DP_MPLLB_STATE remains 1,
* which indicate that PLL disable attempt actually didnt go through.
* As a workaround, insert PHY lane enable/disable before PLL disable.
*/
void dcn21_PLAT_58856_wa(struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
if (!pipe_ctx->stream->dpms_off)
return;
pipe_ctx->stream->dpms_off = false;
core_link_enable_stream(context, pipe_ctx);
core_link_disable_stream(pipe_ctx);
pipe_ctx->stream->dpms_off = true;
}
...@@ -44,4 +44,7 @@ void dcn21_optimize_pwr_state( ...@@ -44,4 +44,7 @@ void dcn21_optimize_pwr_state(
const struct dc *dc, const struct dc *dc,
struct dc_state *context); struct dc_state *context);
void dcn21_PLAT_58856_wa(struct dc_state *context,
struct pipe_ctx *pipe_ctx);
#endif /* __DC_HWSS_DCN21_H__ */ #endif /* __DC_HWSS_DCN21_H__ */
...@@ -130,6 +130,7 @@ static const struct hwseq_private_funcs dcn21_private_funcs = { ...@@ -130,6 +130,7 @@ static const struct hwseq_private_funcs dcn21_private_funcs = {
.dccg_init = dcn20_dccg_init, .dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn20_set_blend_lut, .set_blend_lut = dcn20_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut, .set_shaper_3dlut = dcn20_set_shaper_3dlut,
.PLAT_58856_wa = dcn21_PLAT_58856_wa,
}; };
void dcn21_hw_sequencer_construct(struct dc *dc) void dcn21_hw_sequencer_construct(struct dc *dc)
......
...@@ -145,6 +145,8 @@ struct hwseq_private_funcs { ...@@ -145,6 +145,8 @@ struct hwseq_private_funcs {
const struct dc_plane_state *plane_state); const struct dc_plane_state *plane_state);
bool (*set_shaper_3dlut)(struct pipe_ctx *pipe_ctx, bool (*set_shaper_3dlut)(struct pipe_ctx *pipe_ctx,
const struct dc_plane_state *plane_state); const struct dc_plane_state *plane_state);
void (*PLAT_58856_wa)(struct dc_state *context,
struct pipe_ctx *pipe_ctx);
}; };
struct dce_hwseq { struct dce_hwseq {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment