drm/amd/display: Update display endpoint control path.
[Why] Some display endpoints may be dynamically mapped to the link encoders which drive them. [How] Update the code paths for display enabling/disabling to accommodate the dynamic association between links and link encoders. Signed-off-by: Jimmy Kizito <Jimmy.Kizito@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Anson Jacob <Anson.Jacob@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
f42ef862fb
commit
79ed7354d7
@ -1728,11 +1728,16 @@ bool perform_link_training_with_retries(
|
|||||||
if (link->aux_access_disabled) {
|
if (link->aux_access_disabled) {
|
||||||
dc_link_dp_perform_link_training_skip_aux(link, link_setting);
|
dc_link_dp_perform_link_training_skip_aux(link, link_setting);
|
||||||
return true;
|
return true;
|
||||||
} else if (dc_link_dp_perform_link_training(
|
} else {
|
||||||
link,
|
enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
|
||||||
link_setting,
|
|
||||||
skip_video_pattern) == LINK_TRAINING_SUCCESS)
|
status = dc_link_dp_perform_link_training(
|
||||||
return true;
|
link,
|
||||||
|
link_setting,
|
||||||
|
skip_video_pattern);
|
||||||
|
if (status == LINK_TRAINING_SUCCESS)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* latest link training still fail, skip delay and keep PHY on
|
/* latest link training still fail, skip delay and keep PHY on
|
||||||
*/
|
*/
|
||||||
|
@ -127,6 +127,32 @@ static enum engine_id find_first_avail_link_enc(
|
|||||||
return eng_id;
|
return eng_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return stream using DIG link encoder resource. NULL if unused. */
|
||||||
|
static struct dc_stream_state *get_stream_using_link_enc(
|
||||||
|
struct dc_state *state,
|
||||||
|
enum engine_id eng_id)
|
||||||
|
{
|
||||||
|
struct dc_stream_state *stream = NULL;
|
||||||
|
int stream_idx = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < state->stream_count; i++) {
|
||||||
|
struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
|
||||||
|
|
||||||
|
if (assignment.valid && (assignment.eng_id == eng_id)) {
|
||||||
|
stream_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream_idx != -1)
|
||||||
|
stream = state->streams[stream_idx];
|
||||||
|
else
|
||||||
|
dm_output_to_console("%s: No stream using DIG(%d).\n", __func__, eng_id);
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
void link_enc_cfg_init(
|
void link_enc_cfg_init(
|
||||||
struct dc *dc,
|
struct dc *dc,
|
||||||
struct dc_state *state)
|
struct dc_state *state)
|
||||||
@ -202,3 +228,76 @@ void link_enc_cfg_link_enc_unassign(
|
|||||||
|
|
||||||
update_link_enc_assignment(state, stream, eng_id, false);
|
update_link_enc_assignment(state, stream, eng_id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool link_enc_cfg_is_transmitter_mappable(
|
||||||
|
struct dc_state *state,
|
||||||
|
struct link_encoder *link_enc)
|
||||||
|
{
|
||||||
|
bool is_mappable = false;
|
||||||
|
enum engine_id eng_id = link_enc->preferred_engine;
|
||||||
|
struct dc_stream_state *stream = get_stream_using_link_enc(state, eng_id);
|
||||||
|
|
||||||
|
if (stream)
|
||||||
|
is_mappable = stream->link->is_dig_mapping_flexible;
|
||||||
|
|
||||||
|
return is_mappable;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dc_link *link_enc_cfg_get_link_using_link_enc(
|
||||||
|
struct dc_state *state,
|
||||||
|
enum engine_id eng_id)
|
||||||
|
{
|
||||||
|
struct dc_link *link = NULL;
|
||||||
|
int stream_idx = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < state->stream_count; i++) {
|
||||||
|
struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
|
||||||
|
|
||||||
|
if (assignment.valid && (assignment.eng_id == eng_id)) {
|
||||||
|
stream_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream_idx != -1)
|
||||||
|
link = state->streams[stream_idx]->link;
|
||||||
|
else
|
||||||
|
dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id);
|
||||||
|
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
|
||||||
|
struct dc_state *state,
|
||||||
|
struct dc_link *link)
|
||||||
|
{
|
||||||
|
struct link_encoder *link_enc = NULL;
|
||||||
|
struct display_endpoint_id ep_id;
|
||||||
|
int stream_idx = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ep_id = (struct display_endpoint_id) {
|
||||||
|
.link_id = link->link_id,
|
||||||
|
.ep_type = link->ep_type};
|
||||||
|
|
||||||
|
for (i = 0; i < state->stream_count; i++) {
|
||||||
|
struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
|
||||||
|
|
||||||
|
if (assignment.valid &&
|
||||||
|
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.type == ep_id.link_id.type &&
|
||||||
|
assignment.ep_id.ep_type == ep_id.ep_type) {
|
||||||
|
stream_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream_idx != -1)
|
||||||
|
link_enc = state->streams[stream_idx]->link_enc;
|
||||||
|
else
|
||||||
|
dm_output_to_console("%s: No link encoder used by link(%d).\n", __func__, link->link_index);
|
||||||
|
|
||||||
|
return link_enc;
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "dpcd_defs.h"
|
#include "dpcd_defs.h"
|
||||||
#include "dsc.h"
|
#include "dsc.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#include "link_enc_cfg.h"
|
||||||
#include "clk_mgr.h"
|
#include "clk_mgr.h"
|
||||||
|
|
||||||
static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
|
static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
|
||||||
@ -95,7 +96,7 @@ void dp_enable_link_phy(
|
|||||||
enum clock_source_id clock_source,
|
enum clock_source_id clock_source,
|
||||||
const struct dc_link_settings *link_settings)
|
const struct dc_link_settings *link_settings)
|
||||||
{
|
{
|
||||||
struct link_encoder *link_enc = link->link_enc;
|
struct link_encoder *link_enc;
|
||||||
struct dc *dc = link->ctx->dc;
|
struct dc *dc = link->ctx->dc;
|
||||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||||
|
|
||||||
@ -105,6 +106,13 @@ void dp_enable_link_phy(
|
|||||||
link->dc->res_pool->dp_clock_source;
|
link->dc->res_pool->dp_clock_source;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Link should always be assigned encoder when en-/disabling. */
|
||||||
|
if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
|
||||||
|
link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
|
||||||
|
else
|
||||||
|
link_enc = link->link_enc;
|
||||||
|
ASSERT(link_enc);
|
||||||
|
|
||||||
if (link->connector_signal == SIGNAL_TYPE_EDP) {
|
if (link->connector_signal == SIGNAL_TYPE_EDP) {
|
||||||
link->dc->hwss.edp_power_control(link, true);
|
link->dc->hwss.edp_power_control(link, true);
|
||||||
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
|
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
|
||||||
@ -227,6 +235,14 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
|
|||||||
{
|
{
|
||||||
struct dc *dc = link->ctx->dc;
|
struct dc *dc = link->ctx->dc;
|
||||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||||
|
struct link_encoder *link_enc;
|
||||||
|
|
||||||
|
/* Link should always be assigned encoder when en-/disabling. */
|
||||||
|
if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
|
||||||
|
link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
|
||||||
|
else
|
||||||
|
link_enc = link->link_enc;
|
||||||
|
ASSERT(link_enc);
|
||||||
|
|
||||||
if (!link->wa_flags.dp_keep_receiver_powered)
|
if (!link->wa_flags.dp_keep_receiver_powered)
|
||||||
dp_receiver_power_ctrl(link, false);
|
dp_receiver_power_ctrl(link, false);
|
||||||
@ -234,13 +250,13 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
|
|||||||
if (signal == SIGNAL_TYPE_EDP) {
|
if (signal == SIGNAL_TYPE_EDP) {
|
||||||
if (link->dc->hwss.edp_backlight_control)
|
if (link->dc->hwss.edp_backlight_control)
|
||||||
link->dc->hwss.edp_backlight_control(link, false);
|
link->dc->hwss.edp_backlight_control(link, false);
|
||||||
link->link_enc->funcs->disable_output(link->link_enc, signal);
|
link_enc->funcs->disable_output(link_enc, signal);
|
||||||
link->dc->hwss.edp_power_control(link, false);
|
link->dc->hwss.edp_power_control(link, false);
|
||||||
} else {
|
} else {
|
||||||
if (dmcu != NULL && dmcu->funcs->lock_phy)
|
if (dmcu != NULL && dmcu->funcs->lock_phy)
|
||||||
dmcu->funcs->lock_phy(dmcu);
|
dmcu->funcs->lock_phy(dmcu);
|
||||||
|
|
||||||
link->link_enc->funcs->disable_output(link->link_enc, signal);
|
link_enc->funcs->disable_output(link_enc, signal);
|
||||||
|
|
||||||
if (dmcu != NULL && dmcu->funcs->unlock_phy)
|
if (dmcu != NULL && dmcu->funcs->unlock_phy)
|
||||||
dmcu->funcs->unlock_phy(dmcu);
|
dmcu->funcs->unlock_phy(dmcu);
|
||||||
|
@ -65,4 +65,22 @@ void link_enc_cfg_link_enc_unassign(
|
|||||||
struct dc_state *state,
|
struct dc_state *state,
|
||||||
struct dc_stream_state *stream);
|
struct dc_stream_state *stream);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether the transmitter driven by a link encoder is a mappable
|
||||||
|
* endpoint.
|
||||||
|
*/
|
||||||
|
bool link_enc_cfg_is_transmitter_mappable(
|
||||||
|
struct dc_state *state,
|
||||||
|
struct link_encoder *link_enc);
|
||||||
|
|
||||||
|
/* Return link using DIG link encoder resource. NULL if unused. */
|
||||||
|
struct dc_link *link_enc_cfg_get_link_using_link_enc(
|
||||||
|
struct dc_state *state,
|
||||||
|
enum engine_id eng_id);
|
||||||
|
|
||||||
|
/* Return DIG link encoder used by link. NULL if unused. */
|
||||||
|
struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
|
||||||
|
struct dc_state *state,
|
||||||
|
struct dc_link *link);
|
||||||
|
|
||||||
#endif /* DC_INC_LINK_ENC_CFG_H_ */
|
#endif /* DC_INC_LINK_ENC_CFG_H_ */
|
||||||
|
Reference in New Issue
Block a user