Commit 64d283cb authored by Jimmy Kizito's avatar Jimmy Kizito Committed by Alex Deucher

drm/amd/display: Fix dynamic link encoder access.

[Why]
Assuming DIG link encoders are statically mapped to links can cause
system instability due to null pointer accesses.

[How]
- Add checks for non-null link encoder pointers before trying to access
them.
- When a hardware platform uses dynamic DIG assignment (i.e. resource
function 'link_encs_assign' defined) and a link supports flexible
mapping to DIGs, use the link_enc_cfg API to access the DIG assigned to
a link or stream.
Reviewed-by: default avatarMeenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Acked-by: default avatarMikita Lipski <mikita.lipski@amd.com>
Signed-off-by: default avatarJimmy Kizito <Jimmy.Kizito@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 035f5496
...@@ -87,7 +87,7 @@ int dcn31_get_active_display_cnt_wa( ...@@ -87,7 +87,7 @@ int dcn31_get_active_display_cnt_wa(
const struct dc_link *link = dc->links[i]; const struct dc_link *link = dc->links[i];
/* abusing the fact that the dig and phy are coupled to see if the phy is enabled */ /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */
if (link->link_enc->funcs->is_dig_enabled && if (link->link_enc && link->link_enc->funcs->is_dig_enabled &&
link->link_enc->funcs->is_dig_enabled(link->link_enc)) link->link_enc->funcs->is_dig_enabled(link->link_enc))
display_count++; display_count++;
} }
......
...@@ -3457,6 +3457,10 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) ...@@ -3457,6 +3457,10 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
{ {
struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp; struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct link_encoder *link_enc = NULL;
#endif
if (cp_psp && cp_psp->funcs.update_stream_config) { if (cp_psp && cp_psp->funcs.update_stream_config) {
struct cp_psp_stream_config config = {0}; struct cp_psp_stream_config config = {0};
enum dp_panel_mode panel_mode = enum dp_panel_mode panel_mode =
...@@ -3468,8 +3472,21 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) ...@@ -3468,8 +3472,21 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst; config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst;
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA; config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA;
config.link_enc_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY) {
config.phy_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; link_enc = pipe_ctx->stream->link->link_enc;
config.phy_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
} else if (pipe_ctx->stream->link->dc->res_pool->funcs->link_encs_assign) {
/* Use link encoder assignment from current DC state - which may differ from the DC state to be
* committed - when updating PSP config.
*/
link_enc = link_enc_cfg_get_link_enc_used_by_stream(
pipe_ctx->stream->link->dc->current_state,
pipe_ctx->stream);
config.phy_idx = 0; /* Clear phy_idx for non-physical display endpoints. */
}
ASSERT(link_enc);
if (link_enc)
config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
if (is_dp_128b_132b_signal(pipe_ctx)) { if (is_dp_128b_132b_signal(pipe_ctx)) {
config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0; config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0;
config.link_enc_idx = pipe_ctx->stream->link->hpo_dp_link_enc->inst; config.link_enc_idx = pipe_ctx->stream->link->hpo_dp_link_enc->inst;
...@@ -3576,6 +3593,7 @@ void core_link_enable_stream( ...@@ -3576,6 +3593,7 @@ void core_link_enable_stream(
struct dc_stream_state *stream = pipe_ctx->stream; struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->sink->link; struct dc_link *link = stream->sink->link;
enum dc_status status; enum dc_status status;
struct link_encoder *link_enc;
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO; enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO;
#endif #endif
...@@ -3585,14 +3603,21 @@ void core_link_enable_stream( ...@@ -3585,14 +3603,21 @@ void core_link_enable_stream(
dc_is_virtual_signal(pipe_ctx->stream->signal)) dc_is_virtual_signal(pipe_ctx->stream->signal))
return; return;
if (dc->res_pool->funcs->link_encs_assign && stream->link->ep_type != DISPLAY_ENDPOINT_PHY)
link_enc = stream->link_enc;
else
link_enc = stream->link->link_enc;
ASSERT(link_enc);
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
if (!dc_is_virtual_signal(pipe_ctx->stream->signal) if (!dc_is_virtual_signal(pipe_ctx->stream->signal)
&& !is_dp_128b_132b_signal(pipe_ctx)) { && !is_dp_128b_132b_signal(pipe_ctx)) {
#else #else
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) { if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) {
#endif #endif
stream->link->link_enc->funcs->setup( if (link_enc)
stream->link->link_enc, link_enc->funcs->setup(
link_enc,
pipe_ctx->stream->signal); pipe_ctx->stream->signal);
pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync( pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync(
pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.stream_enc,
...@@ -3748,8 +3773,9 @@ void core_link_enable_stream( ...@@ -3748,8 +3773,9 @@ void core_link_enable_stream(
#else #else
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
#endif #endif
stream->link->link_enc->funcs->setup( if (link_enc)
stream->link->link_enc, link_enc->funcs->setup(
link_enc,
pipe_ctx->stream->signal); pipe_ctx->stream->signal);
dc->hwss.enable_stream(pipe_ctx); dc->hwss.enable_stream(pipe_ctx);
......
...@@ -2624,13 +2624,27 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) ...@@ -2624,13 +2624,27 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
{ {
struct link_encoder *link_enc = NULL;
if (!max_link_enc_cap) { if (!max_link_enc_cap) {
DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__); DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__);
return false; return false;
} }
if (link->link_enc->funcs->get_max_link_cap) { /* Links supporting dynamically assigned link encoder will be assigned next
link->link_enc->funcs->get_max_link_cap(link->link_enc, max_link_enc_cap); * available encoder if one not already assigned.
*/
if (link->is_dig_mapping_flexible &&
link->dc->res_pool->funcs->link_encs_assign) {
link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
if (link_enc == NULL)
link_enc = link_enc_cfg_get_next_avail_link_enc(link->dc, link->dc->current_state);
} else
link_enc = link->link_enc;
ASSERT(link_enc);
if (link_enc && link_enc->funcs->get_max_link_cap) {
link_enc->funcs->get_max_link_cap(link_enc, max_link_enc_cap);
return true; return true;
} }
...@@ -2646,9 +2660,23 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) ...@@ -2646,9 +2660,23 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link)
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
enum dc_link_rate lttpr_max_link_rate; enum dc_link_rate lttpr_max_link_rate;
#endif #endif
struct link_encoder *link_enc = NULL;
/* Links supporting dynamically assigned link encoder will be assigned next
* available encoder if one not already assigned.
*/
if (link->is_dig_mapping_flexible &&
link->dc->res_pool->funcs->link_encs_assign) {
link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
if (link_enc == NULL)
link_enc = link_enc_cfg_get_next_avail_link_enc(link->dc, link->dc->current_state);
} else
link_enc = link->link_enc;
ASSERT(link_enc);
/* get max link encoder capability */ /* get max link encoder capability */
link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap); if (link_enc)
link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap);
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
if (max_link_cap.link_rate >= LINK_RATE_UHBR10 && if (max_link_cap.link_rate >= LINK_RATE_UHBR10 &&
!link->hpo_dp_link_enc) !link->hpo_dp_link_enc)
...@@ -2867,7 +2895,7 @@ bool dp_verify_link_cap( ...@@ -2867,7 +2895,7 @@ bool dp_verify_link_cap(
* PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle, * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle,
* so add extra cycle of enabling and disabling the PHY before first link training. * so add extra cycle of enabling and disabling the PHY before first link training.
*/ */
if (link->link_enc->features.flags.bits.DP_IS_USB_C && if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C &&
link->dc->debug.usbc_combo_phy_reset_wa) { link->dc->debug.usbc_combo_phy_reset_wa) {
dp_enable_link_phy(link, link->connector_signal, dp_cs_id, cur); dp_enable_link_phy(link, link->connector_signal, dp_cs_id, cur);
dp_disable_link_phy(link, link->connector_signal); dp_disable_link_phy(link, link->connector_signal);
......
...@@ -139,7 +139,7 @@ static struct dc_stream_state *get_stream_using_link_enc( ...@@ -139,7 +139,7 @@ static struct dc_stream_state *get_stream_using_link_enc(
for (i = 0; i < state->stream_count; i++) { for (i = 0; i < state->stream_count; i++) {
struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
if (assignment.valid && (assignment.eng_id == eng_id)) { if ((assignment.valid == true) && (assignment.eng_id == eng_id)) {
stream_idx = i; stream_idx = i;
break; break;
} }
...@@ -254,7 +254,7 @@ struct dc_link *link_enc_cfg_get_link_using_link_enc( ...@@ -254,7 +254,7 @@ struct dc_link *link_enc_cfg_get_link_using_link_enc(
for (i = 0; i < state->stream_count; i++) { for (i = 0; i < state->stream_count; i++) {
struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
if (assignment.valid && (assignment.eng_id == eng_id)) { if ((assignment.valid == true) && (assignment.eng_id == eng_id)) {
stream_idx = i; stream_idx = i;
break; break;
} }
...@@ -274,7 +274,6 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( ...@@ -274,7 +274,6 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
{ {
struct link_encoder *link_enc = NULL; struct link_encoder *link_enc = NULL;
struct display_endpoint_id ep_id; struct display_endpoint_id ep_id;
int stream_idx = -1;
int i; int i;
ep_id = (struct display_endpoint_id) { ep_id = (struct display_endpoint_id) {
...@@ -283,20 +282,15 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( ...@@ -283,20 +282,15 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
for (i = 0; i < state->stream_count; i++) { for (i = 0; i < state->stream_count; i++) {
struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
if (assignment.valid == true &&
if (assignment.valid &&
assignment.ep_id.link_id.id == ep_id.link_id.id && assignment.ep_id.link_id.id == ep_id.link_id.id &&
assignment.ep_id.link_id.enum_id == ep_id.link_id.enum_id && assignment.ep_id.link_id.enum_id == ep_id.link_id.enum_id &&
assignment.ep_id.link_id.type == ep_id.link_id.type && assignment.ep_id.link_id.type == ep_id.link_id.type &&
assignment.ep_id.ep_type == ep_id.ep_type) { assignment.ep_id.ep_type == ep_id.ep_type) {
stream_idx = i; link_enc = link->dc->res_pool->link_encoders[assignment.eng_id - ENGINE_ID_DIGA];
break;
} }
} }
if (stream_idx != -1)
link_enc = state->streams[stream_idx]->link_enc;
return link_enc; return link_enc;
} }
...@@ -313,3 +307,14 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc( ...@@ -313,3 +307,14 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc(
return link_enc; return link_enc;
} }
struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream(
struct dc_state *state,
const struct dc_stream_state *stream)
{
struct link_encoder *link_enc;
link_enc = link_enc_cfg_get_link_enc_used_by_link(state, stream->link);
return link_enc;
}
...@@ -452,6 +452,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, ...@@ -452,6 +452,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,
if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only) if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
(&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio); (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
if (link->link_enc)
link->link_enc->funcs->disable_output( link->link_enc->funcs->disable_output(
link->link_enc, link->link_enc,
SIGNAL_TYPE_DISPLAY_PORT); SIGNAL_TYPE_DISPLAY_PORT);
......
...@@ -2970,7 +2970,8 @@ enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) ...@@ -2970,7 +2970,8 @@ enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
res = DC_FAIL_CONTROLLER_VALIDATE; res = DC_FAIL_CONTROLLER_VALIDATE;
if (res == DC_OK) { if (res == DC_OK) {
if (!link->link_enc->funcs->validate_output_with_stream( if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
!link->link_enc->funcs->validate_output_with_stream(
link->link_enc, stream)) link->link_enc, stream))
res = DC_FAIL_ENC_VALIDATE; res = DC_FAIL_ENC_VALIDATE;
} }
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "transform.h" #include "transform.h"
#include "stream_encoder.h" #include "stream_encoder.h"
#include "link_encoder.h" #include "link_encoder.h"
#include "link_enc_cfg.h"
#include "link_hwss.h" #include "link_hwss.h"
#include "dc_link_dp.h" #include "dc_link_dp.h"
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
...@@ -1192,6 +1193,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -1192,6 +1193,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
struct dc_stream_state *stream = pipe_ctx->stream; struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link; struct dc_link *link = stream->link;
struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc *dc = pipe_ctx->stream->ctx->dc;
struct link_encoder *link_enc = NULL;
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) { if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) {
pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets(
...@@ -1213,6 +1215,13 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -1213,6 +1215,13 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
dc->hwss.disable_audio_stream(pipe_ctx); dc->hwss.disable_audio_stream(pipe_ctx);
/* Link encoder may have been dynamically assigned to non-physical display endpoint. */
if (link->ep_type == DISPLAY_ENDPOINT_PHY)
link_enc = link->link_enc;
else if (dc->res_pool->funcs->link_encs_assign)
link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
ASSERT(link_enc);
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx)) { if (is_dp_128b_132b_signal(pipe_ctx)) {
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->disable( pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->disable(
...@@ -1220,13 +1229,15 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -1220,13 +1229,15 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
setup_dp_hpo_stream(pipe_ctx, false); setup_dp_hpo_stream(pipe_ctx, false);
/* TODO - DP2.0 HW: unmap stream from link encoder here */ /* TODO - DP2.0 HW: unmap stream from link encoder here */
} else { } else {
link->link_enc->funcs->connect_dig_be_to_fe( if (link_enc)
link->link_enc, link_enc->funcs->connect_dig_be_to_fe(
link_enc,
pipe_ctx->stream_res.stream_enc->id, pipe_ctx->stream_res.stream_enc->id,
false); false);
} }
#else #else
link->link_enc->funcs->connect_dig_be_to_fe( if (link_enc)
link_enc->funcs->connect_dig_be_to_fe(
link->link_enc, link->link_enc,
pipe_ctx->stream_res.stream_enc->id, pipe_ctx->stream_res.stream_enc->id,
false); false);
...@@ -1666,6 +1677,7 @@ static void power_down_encoders(struct dc *dc) ...@@ -1666,6 +1677,7 @@ static void power_down_encoders(struct dc *dc)
if (signal != SIGNAL_TYPE_EDP) if (signal != SIGNAL_TYPE_EDP)
signal = SIGNAL_TYPE_NONE; signal = SIGNAL_TYPE_NONE;
if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY)
dc->links[i]->link_enc->funcs->disable_output( dc->links[i]->link_enc->funcs->disable_output(
dc->links[i]->link_enc, signal); dc->links[i]->link_enc, signal);
......
...@@ -1296,7 +1296,7 @@ struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link( ...@@ -1296,7 +1296,7 @@ struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link(
* in daisy chain use case * in daisy chain use case
*/ */
j = i; j = i;
if (pool->stream_enc[i]->id == if (link->ep_type == DISPLAY_ENDPOINT_PHY && pool->stream_enc[i]->id ==
link->link_enc->preferred_engine) link->link_enc->preferred_engine)
return pool->stream_enc[i]; return pool->stream_enc[i];
} }
......
...@@ -2381,6 +2381,13 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) ...@@ -2381,6 +2381,13 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
uint32_t active_total_with_borders; uint32_t active_total_with_borders;
uint32_t early_control = 0; uint32_t early_control = 0;
struct timing_generator *tg = pipe_ctx->stream_res.tg; struct timing_generator *tg = pipe_ctx->stream_res.tg;
struct link_encoder *link_enc;
if (link->is_dig_mapping_flexible &&
link->dc->res_pool->funcs->link_encs_assign)
link_enc = pipe_ctx->stream->link_enc;
else
link_enc = link->link_enc;
/* For MST, there are multiply stream go to only one link. /* For MST, there are multiply stream go to only one link.
* connect DIG back_end to front_end while enable_stream and * connect DIG back_end to front_end while enable_stream and
...@@ -2397,9 +2404,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) ...@@ -2397,9 +2404,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
link->hpo_dp_link_enc->inst); link->hpo_dp_link_enc->inst);
} }
if (!is_dp_128b_132b_signal(pipe_ctx)) if (!is_dp_128b_132b_signal(pipe_ctx) && link_enc)
link->link_enc->funcs->connect_dig_be_to_fe( link_enc->funcs->connect_dig_be_to_fe(
link->link_enc, pipe_ctx->stream_res.stream_enc->id, true); link_enc, pipe_ctx->stream_res.stream_enc->id, true);
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (dc_is_dp_signal(pipe_ctx->stream->signal))
dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE);
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
#include "dce/dce_aux.h" #include "dce/dce_aux.h"
#include "dce/dce_i2c.h" #include "dce/dce_i2c.h"
#include "vm_helper.h" #include "vm_helper.h"
#include "link_enc_cfg.h"
#include "amdgpu_socbb.h" #include "amdgpu_socbb.h"
...@@ -1596,12 +1597,29 @@ static void get_pixel_clock_parameters( ...@@ -1596,12 +1597,29 @@ static void get_pixel_clock_parameters(
const struct dc_stream_state *stream = pipe_ctx->stream; const struct dc_stream_state *stream = pipe_ctx->stream;
struct pipe_ctx *odm_pipe; struct pipe_ctx *odm_pipe;
int opp_cnt = 1; int opp_cnt = 1;
struct dc_link *link = stream->link;
struct link_encoder *link_enc = NULL;
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
opp_cnt++; opp_cnt++;
pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
pixel_clk_params->encoder_object_id = stream->link->link_enc->id;
/* Links supporting dynamically assigned link encoder will be assigned next
* available encoder if one not already assigned.
*/
if (link->is_dig_mapping_flexible &&
link->dc->res_pool->funcs->link_encs_assign) {
link_enc = link_enc_cfg_get_link_enc_used_by_stream(stream->link->dc->current_state, stream);
if (link_enc == NULL)
link_enc = link_enc_cfg_get_next_avail_link_enc(stream->link->dc,
stream->link->dc->current_state);
} else
link_enc = stream->link->link_enc;
ASSERT(link_enc);
if (link_enc)
pixel_clk_params->encoder_object_id = link_enc->id;
pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->signal_type = pipe_ctx->stream->signal;
pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1;
/* TODO: un-hardcode*/ /* TODO: un-hardcode*/
......
...@@ -157,6 +157,9 @@ void dcn31_init_hw(struct dc *dc) ...@@ -157,6 +157,9 @@ void dcn31_init_hw(struct dc *dc)
*/ */
struct dc_link *link = dc->links[i]; struct dc_link *link = dc->links[i];
if (link->ep_type != DISPLAY_ENDPOINT_PHY)
continue;
link->link_enc->funcs->hw_init(link->link_enc); link->link_enc->funcs->hw_init(link->link_enc);
/* Check for enabled DIG to identify enabled display */ /* Check for enabled DIG to identify enabled display */
...@@ -184,7 +187,8 @@ void dcn31_init_hw(struct dc *dc) ...@@ -184,7 +187,8 @@ void dcn31_init_hw(struct dc *dc)
&dpcd_power_state, sizeof(dpcd_power_state)); &dpcd_power_state, sizeof(dpcd_power_state));
if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) { if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) {
/* blank dp stream before power off receiver*/ /* blank dp stream before power off receiver*/
if (dc->links[i]->link_enc->funcs->get_dig_frontend) { if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY &&
dc->links[i]->link_enc->funcs->get_dig_frontend) {
unsigned int fe; unsigned int fe;
fe = dc->links[i]->link_enc->funcs->get_dig_frontend( fe = dc->links[i]->link_enc->funcs->get_dig_frontend(
...@@ -248,7 +252,8 @@ void dcn31_init_hw(struct dc *dc) ...@@ -248,7 +252,8 @@ void dcn31_init_hw(struct dc *dc)
for (i = 0; i < dc->link_count; i++) { for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i]; struct dc_link *link = dc->links[i];
if (link->link_enc->funcs->is_dig_enabled && if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
link->link_enc->funcs->is_dig_enabled &&
link->link_enc->funcs->is_dig_enabled(link->link_enc) && link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
dc->hwss.power_down) { dc->hwss.power_down) {
dc->hwss.power_down(dc); dc->hwss.power_down(dc);
......
...@@ -88,4 +88,9 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc( ...@@ -88,4 +88,9 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc(
const struct dc *dc, const struct dc *dc,
const struct dc_state *state); const struct dc_state *state);
/* Return DIG link encoder used by stream. NULL if unused. */
struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream(
struct dc_state *state,
const struct dc_stream_state *stream);
#endif /* DC_INC_LINK_ENC_CFG_H_ */ #endif /* DC_INC_LINK_ENC_CFG_H_ */
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