Skip to content

Commit

Permalink
drm/amd/display: rework recent update PHY state commit
Browse files Browse the repository at this point in the history
[why]
Original change 594b237 ("drm/amd/display: Add
interface to track PHY state") was implemented by assuming stream's
dpms off is equivalent to PHY power off.
This assumption doesn't hold in following situations:
1. MST multiple stream scenario, where multiple streams are sharing the
same PHY output. Toggle dpms off for one of the stream doesn't power
off the PHY due to the presence of other streams.
2. enable stream failure scenario, where enable stream fails due to
failure of link training. This will cause DPMS off is set to false, while
the actual PHY power state is off in certain cases.
Due to the problematic assumption, the logic will skip disabling
other streams for MST multiple stream scenario, therefore PHY is
not actually powered off.

[how]
1. Rework this refactor by moving PHY state update down to hardware
level, where we update PHY state in place when hardware sequencer
is actually changing the power state of the PHY hardware.
2. Reimplement symclk on TX off workaround in place when we are actually
calling transmitter control to power off PHY in dcn32. Note the workaround is
added due to the lack of proper software interface to set TX while keeping
symclk on. We plan to address this interface problem so we can set TX off
only without affecting symclk in future dcn versions.

Fixes: 594b237 ("drm/amd/display: Add interface to track PHY state")
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Wayne Lin <wayne.lin@amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Wenjing Liu authored and Alex Deucher committed Sep 19, 2022
1 parent 10faf07 commit 9c75891
Show file tree
Hide file tree
Showing 28 changed files with 357 additions and 177 deletions.
19 changes: 3 additions & 16 deletions drivers/gpu/drm/amd/display/dc/core/dc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1184,11 +1184,7 @@ 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) {
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);
core_link_disable_stream(pipe);
pipe->stream->dpms_off = false;
}
}
Expand Down Expand Up @@ -3061,11 +3057,7 @@ static void commit_planes_do_stream_update(struct dc *dc,

if (stream_update->dpms_off) {
if (*stream_update->dpms_off) {
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);
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);
Expand All @@ -3075,12 +3067,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
} else {
if (get_seamless_boot_stream_count(context) == 0)
dc->hwss.prepare_bandwidth(dc, dc->current_state);

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);
core_link_enable_stream(dc->current_state, pipe_ctx);
}
}

Expand Down
20 changes: 11 additions & 9 deletions drivers/gpu/drm/amd/display/dc/core/dc_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -2644,9 +2644,8 @@ static void disable_link(struct dc_link *link, const struct link_resource *link_
dp_set_fec_ready(link, link_res, false);
}
}
} else {
if (signal != SIGNAL_TYPE_VIRTUAL)
link->link_enc->funcs->disable_output(link->link_enc, signal);
} else if (signal != SIGNAL_TYPE_VIRTUAL) {
link->dc->hwss.disable_link_output(link, link_res, signal);
}

if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
Expand All @@ -2668,6 +2667,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
bool is_over_340mhz = false;
bool is_vga_mode = (stream->timing.h_addressable == 640)
&& (stream->timing.v_addressable == 480);
struct dc *dc = pipe_ctx->stream->ctx->dc;

if (stream->phy_pix_clk == 0)
stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
Expand Down Expand Up @@ -2707,11 +2707,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
display_color_depth = COLOR_DEPTH_888;

link->link_enc->funcs->enable_tmds_output(
link->link_enc,
dc->hwss.enable_tmds_link_output(
link,
&pipe_ctx->link_res,
pipe_ctx->stream->signal,
pipe_ctx->clock_source->id,
display_color_depth,
pipe_ctx->stream->signal,
stream->phy_pix_clk);

if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
Expand All @@ -2722,15 +2723,16 @@ static void enable_link_lvds(struct pipe_ctx *pipe_ctx)
{
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
struct dc *dc = stream->ctx->dc;

if (stream->phy_pix_clk == 0)
stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;

memset(&stream->link->cur_link_settings, 0,
sizeof(struct dc_link_settings));

link->link_enc->funcs->enable_lvds_output(
link->link_enc,
dc->hwss.enable_lvds_link_output(
link,
&pipe_ctx->link_res,
pipe_ctx->clock_source->id,
stream->phy_pix_clk);

Expand Down
96 changes: 7 additions & 89 deletions drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4518,25 +4518,15 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
for (i = 0; i < MAX_PIPES; i++) {
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) {
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);
}
pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
core_link_disable_stream(pipe_ctx);
}

for (i = 0; i < MAX_PIPES; i++) {
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) {
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);
}
pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
core_link_enable_stream(link->dc->current_state, pipe_ctx);
}
}

Expand Down Expand Up @@ -7077,60 +7067,9 @@ void dp_enable_link_phy(
enum clock_source_id clock_source,
const struct dc_link_settings *link_settings)
{
struct dc *dc = link->ctx->dc;
struct dmcu *dmcu = dc->res_pool->dmcu;
struct pipe_ctx *pipes =
link->dc->current_state->res_ctx.pipe_ctx;
struct clock_source *dp_cs =
link->dc->res_pool->dp_clock_source;
const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
unsigned int i;

if (link->connector_signal == SIGNAL_TYPE_EDP) {
if (!link->dc->config.edp_no_power_sequencing)
link->dc->hwss.edp_power_control(link, true);
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
}

/* If the current pixel clock source is not DTO(happens after
* switching from HDMI passive dongle to DP on the same connector),
* switch the pixel clock source to DTO.
*/
for (i = 0; i < MAX_PIPES; i++) {
if (pipes[i].stream != NULL &&
pipes[i].stream->link == link) {
if (pipes[i].clock_source != NULL &&
pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
pipes[i].clock_source = dp_cs;
pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
pipes[i].stream->timing.pix_clk_100hz;
pipes[i].clock_source->funcs->program_pix_clk(
pipes[i].clock_source,
&pipes[i].stream_res.pix_clk_params,
dp_get_link_encoding_format(link_settings),
&pipes[i].pll_settings);
}
}
}

link->dc->hwss.enable_dp_link_output(link, link_res, signal,
clock_source, link_settings);
link->cur_link_settings = *link_settings;

if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
if (dc->clk_mgr->funcs->notify_link_rate_change)
dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
}

if (dmcu != NULL && dmcu->funcs->lock_phy)
dmcu->funcs->lock_phy(dmcu);

if (link_hwss->ext.enable_dp_link_output)
link_hwss->ext.enable_dp_link_output(link, link_res, signal,
clock_source, link_settings);

if (dmcu != NULL && dmcu->funcs->unlock_phy)
dmcu->funcs->unlock_phy(dmcu);

dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY);
dp_receiver_power_ctrl(link, true);
}

Expand Down Expand Up @@ -7205,29 +7144,8 @@ void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_
enum signal_type signal)
{
struct dc *dc = link->ctx->dc;
struct dmcu *dmcu = dc->res_pool->dmcu;
const struct link_hwss *link_hwss = get_link_hwss(link, link_res);

if (!link->wa_flags.dp_keep_receiver_powered)
dp_receiver_power_ctrl(link, false);

if (signal == SIGNAL_TYPE_EDP) {
if (link->dc->hwss.edp_backlight_control)
link->dc->hwss.edp_backlight_control(link, false);
if (link_hwss->ext.disable_dp_link_output)
link_hwss->ext.disable_dp_link_output(link, link_res, signal);
link->dc->hwss.edp_power_control(link, false);
} else {
if (dmcu != NULL && dmcu->funcs->lock_phy)
dmcu->funcs->lock_phy(dmcu);
if (link_hwss->ext.disable_dp_link_output)
link_hwss->ext.disable_dp_link_output(link, link_res, signal);
if (dmcu != NULL && dmcu->funcs->unlock_phy)
dmcu->funcs->unlock_phy(dmcu);
}

dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);

dc->hwss.disable_link_output(link, link_res, signal);
/* Clear current link setting.*/
memset(&link->cur_link_settings, 0,
sizeof(link->cur_link_settings));
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/amd/display/dc/dc_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ struct dc_link {
struct gpio *hpd_gpio;
enum dc_link_fec_state fec_state;
struct dc_panel_config panel_config;
enum phy_state phy_state;
struct phy_state phy_state;
};

const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
Expand Down
Loading

0 comments on commit 9c75891

Please sign in to comment.