drm/amd/display: Add interface to track PHY state
[Why] Sometimes pixel clock needs to remain active after transmitter disable. [How] Use update_phy_state to track PHY state after stream enable/disable and program pixel clock as needed. Reviewed-by: Alvin Lee <alvin.lee2@amd.com> Acked-by: Brian Chang <Brian.Chang@amd.com> Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com> Signed-off-by: Alvin Lee <alvin.lee2@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
b68ea8af4a
commit
594b237b9a
@ -1180,7 +1180,11 @@ static void disable_vbios_mode_if_required(
|
||||
pipe->stream_res.pix_clk_params.requested_pix_clk_100hz;
|
||||
|
||||
if (pix_clk_100hz != requested_pix_clk_100hz) {
|
||||
core_link_disable_stream(pipe);
|
||||
if (dc->hwss.update_phy_state)
|
||||
dc->hwss.update_phy_state(dc->current_state,
|
||||
pipe, TX_OFF_SYMCLK_OFF);
|
||||
else
|
||||
core_link_disable_stream(pipe);
|
||||
pipe->stream->dpms_off = false;
|
||||
}
|
||||
}
|
||||
@ -3063,7 +3067,11 @@ static void commit_planes_do_stream_update(struct dc *dc,
|
||||
|
||||
if (stream_update->dpms_off) {
|
||||
if (*stream_update->dpms_off) {
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
if (dc->hwss.update_phy_state)
|
||||
dc->hwss.update_phy_state(dc->current_state,
|
||||
pipe_ctx, TX_OFF_SYMCLK_ON);
|
||||
else
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
/* for dpms, keep acquired resources*/
|
||||
if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
|
||||
pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
|
||||
@ -3074,7 +3082,11 @@ static void commit_planes_do_stream_update(struct dc *dc,
|
||||
if (get_seamless_boot_stream_count(context) == 0)
|
||||
dc->hwss.prepare_bandwidth(dc, dc->current_state);
|
||||
|
||||
core_link_enable_stream(dc->current_state, pipe_ctx);
|
||||
if (dc->hwss.update_phy_state)
|
||||
dc->hwss.update_phy_state(dc->current_state,
|
||||
pipe_ctx, TX_ON_SYMCLK_ON);
|
||||
else
|
||||
core_link_enable_stream(dc->current_state, pipe_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4519,7 +4519,11 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
|
||||
pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
|
||||
if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
|
||||
pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
if (link->dc->hwss.update_phy_state)
|
||||
link->dc->hwss.update_phy_state(link->dc->current_state,
|
||||
pipe_ctx, TX_OFF_SYMCLK_OFF);
|
||||
else
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4527,7 +4531,11 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
|
||||
pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
|
||||
if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
|
||||
pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
|
||||
core_link_enable_stream(link->dc->current_state, pipe_ctx);
|
||||
if (link->dc->hwss.update_phy_state)
|
||||
link->dc->hwss.update_phy_state(link->dc->current_state,
|
||||
pipe_ctx, TX_ON_SYMCLK_ON);
|
||||
else
|
||||
core_link_enable_stream(link->dc->current_state, pipe_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,6 +232,7 @@ struct dc_link {
|
||||
|
||||
struct gpio *hpd_gpio;
|
||||
enum dc_link_fec_state fec_state;
|
||||
enum phy_state phy_state;
|
||||
};
|
||||
|
||||
const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
|
||||
|
@ -1577,8 +1577,12 @@ static enum dc_status apply_single_controller_ctx_to_hw(
|
||||
if (dc_is_dp_signal(pipe_ctx->stream->signal))
|
||||
dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG);
|
||||
|
||||
if (!stream->dpms_off)
|
||||
core_link_enable_stream(context, pipe_ctx);
|
||||
if (!stream->dpms_off) {
|
||||
if (dc->hwss.update_phy_state)
|
||||
dc->hwss.update_phy_state(context, pipe_ctx, TX_ON_SYMCLK_ON);
|
||||
else
|
||||
core_link_enable_stream(context, pipe_ctx);
|
||||
}
|
||||
|
||||
/* DCN3.1 FPGA Workaround
|
||||
* Need to enable HPO DP Stream Encoder before setting OTG master enable.
|
||||
|
@ -2361,9 +2361,12 @@ static void dcn20_reset_back_end_for_pipe(
|
||||
* screen only, the dpms_off would be true but
|
||||
* VBIOS lit up eDP, so check link status too.
|
||||
*/
|
||||
if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
else if (pipe_ctx->stream_res.audio)
|
||||
if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) {
|
||||
if (dc->hwss.update_phy_state)
|
||||
dc->hwss.update_phy_state(dc->current_state, pipe_ctx, TX_OFF_SYMCLK_OFF);
|
||||
else
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
} else if (pipe_ctx->stream_res.audio)
|
||||
dc->hwss.disable_audio_stream(pipe_ctx);
|
||||
|
||||
/* free acquired resources */
|
||||
|
@ -553,9 +553,12 @@ static void dcn31_reset_back_end_for_pipe(
|
||||
* screen only, the dpms_off would be true but
|
||||
* VBIOS lit up eDP, so check link status too.
|
||||
*/
|
||||
if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
else if (pipe_ctx->stream_res.audio)
|
||||
if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) {
|
||||
if (dc->hwss.update_phy_state)
|
||||
dc->hwss.update_phy_state(dc->current_state, pipe_ctx, TX_OFF_SYMCLK_OFF);
|
||||
else
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
} else if (pipe_ctx->stream_res.audio)
|
||||
dc->hwss.disable_audio_stream(pipe_ctx);
|
||||
|
||||
/* free acquired resources */
|
||||
|
@ -1218,3 +1218,35 @@ bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void dcn32_update_phy_state(struct dc_state *state, struct pipe_ctx *pipe_ctx,
|
||||
enum phy_state target_state)
|
||||
{
|
||||
enum phy_state current_state = pipe_ctx->stream->link->phy_state;
|
||||
|
||||
if (current_state == target_state) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
|
||||
if (target_state == TX_OFF_SYMCLK_OFF) {
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
pipe_ctx->stream->link->phy_state = TX_OFF_SYMCLK_OFF;
|
||||
} else if (target_state == TX_ON_SYMCLK_ON) {
|
||||
core_link_enable_stream(state, pipe_ctx);
|
||||
pipe_ctx->stream->link->phy_state = TX_ON_SYMCLK_ON;
|
||||
} else if (target_state == TX_OFF_SYMCLK_ON) {
|
||||
if (current_state == TX_ON_SYMCLK_ON) {
|
||||
core_link_disable_stream(pipe_ctx);
|
||||
pipe_ctx->stream->link->phy_state = TX_OFF_SYMCLK_OFF;
|
||||
}
|
||||
|
||||
pipe_ctx->clock_source->funcs->program_pix_clk(
|
||||
pipe_ctx->clock_source,
|
||||
&pipe_ctx->stream_res.pix_clk_params,
|
||||
dp_get_link_encoding_format(&pipe_ctx->link_config.dp_link_settings),
|
||||
&pipe_ctx->pll_settings);
|
||||
pipe_ctx->stream->link->phy_state = TX_OFF_SYMCLK_ON;
|
||||
} else
|
||||
BREAK_TO_DEBUGGER();
|
||||
}
|
||||
|
@ -84,4 +84,7 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
|
||||
|
||||
bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);
|
||||
|
||||
void dcn32_update_phy_state(struct dc_state *state, struct pipe_ctx *pipe_ctx,
|
||||
enum phy_state target_state);
|
||||
|
||||
#endif /* __DC_HWSS_DCN32_H__ */
|
||||
|
@ -104,6 +104,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
|
||||
.commit_subvp_config = dcn32_commit_subvp_config,
|
||||
.subvp_pipe_control_lock = dcn32_subvp_pipe_control_lock,
|
||||
.update_visual_confirm_color = dcn20_update_visual_confirm_color,
|
||||
.update_phy_state = dcn32_update_phy_state,
|
||||
};
|
||||
|
||||
static const struct hwseq_private_funcs dcn32_private_funcs = {
|
||||
|
@ -268,6 +268,12 @@ enum dc_lut_mode {
|
||||
LUT_RAM_B
|
||||
};
|
||||
|
||||
enum phy_state {
|
||||
TX_OFF_SYMCLK_OFF,
|
||||
TX_ON_SYMCLK_ON,
|
||||
TX_OFF_SYMCLK_ON
|
||||
};
|
||||
|
||||
/**
|
||||
* speakersToChannels
|
||||
*
|
||||
|
@ -245,6 +245,8 @@ struct hw_sequencer_funcs {
|
||||
struct tg_color *color,
|
||||
int mpcc_id);
|
||||
|
||||
void (*update_phy_state)(struct dc_state *state, struct pipe_ctx *pipe_ctx, enum phy_state target_state);
|
||||
|
||||
void (*commit_subvp_config)(struct dc *dc, struct dc_state *context);
|
||||
void (*subvp_pipe_control_lock)(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
|
Loading…
x
Reference in New Issue
Block a user