aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/core/dc_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc_link.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c54
1 files changed, 38 insertions, 16 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 48ab51533d5d..117d8aaf2a9b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -521,11 +521,11 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin
}
#if defined(CONFIG_DRM_AMD_DC_HDCP)
-bool dc_link_is_hdcp14(struct dc_link *link)
+bool dc_link_is_hdcp14(struct dc_link *link, enum signal_type signal)
{
bool ret = false;
- switch (link->connector_signal) {
+ switch (signal) {
case SIGNAL_TYPE_DISPLAY_PORT:
case SIGNAL_TYPE_DISPLAY_PORT_MST:
ret = link->hdcp_caps.bcaps.bits.HDCP_CAPABLE;
@@ -545,11 +545,11 @@ bool dc_link_is_hdcp14(struct dc_link *link)
return ret;
}
-bool dc_link_is_hdcp22(struct dc_link *link)
+bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal)
{
bool ret = false;
- switch (link->connector_signal) {
+ switch (signal) {
case SIGNAL_TYPE_DISPLAY_PORT:
case SIGNAL_TYPE_DISPLAY_PORT_MST:
ret = (link->hdcp_caps.bcaps.bits.HDCP_CAPABLE &&
@@ -690,12 +690,8 @@ static bool detect_dp(struct dc_link *link,
if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
-
- dpcd_set_source_specific_data(link);
-
if (!detect_dp_sink_caps(link))
return false;
-
if (is_mst_supported(link)) {
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
link->type = dc_connection_mst_branch;
@@ -858,6 +854,7 @@ static bool dc_link_detect_helper(struct dc_link *link,
bool same_dpcd = true;
enum dc_connection_type new_connection_type = dc_connection_none;
bool perform_dp_seamless_boot = false;
+ const uint32_t post_oui_delay = 30; // 30ms
DC_LOGGER_INIT(link->ctx->logger);
@@ -870,6 +867,7 @@ static bool dc_link_detect_helper(struct dc_link *link,
// need to re-write OUI and brightness in resume case
if (link->connector_signal == SIGNAL_TYPE_EDP) {
dpcd_set_source_specific_data(link);
+ msleep(post_oui_delay);
dc_link_set_default_brightness_aux(link);
//TODO: use cached
}
@@ -925,8 +923,6 @@ static bool dc_link_detect_helper(struct dc_link *link,
case SIGNAL_TYPE_EDP: {
read_current_link_settings_on_detect(link);
- dpcd_set_source_specific_data(link);
-
detect_edp_sink_caps(link);
read_current_link_settings_on_detect(link);
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
@@ -1544,6 +1540,9 @@ static bool dc_link_construct(struct dc_link *link,
}
}
+ if (bios->funcs->get_atom_dc_golden_table)
+ bios->funcs->get_atom_dc_golden_table(bios);
+
/*
* TODO check if GPIO programmed correctly
*
@@ -1636,6 +1635,7 @@ static enum dc_status enable_link_dp(struct dc_state *state,
int i;
bool apply_seamless_boot_optimization = false;
uint32_t bl_oled_enable_delay = 50; // in ms
+ const uint32_t post_oui_delay = 30; // 30ms
// check for seamless boot
for (i = 0; i < state->stream_count; i++) {
@@ -1662,6 +1662,8 @@ static enum dc_status enable_link_dp(struct dc_state *state,
// during mode switch we do DP_SET_POWER off then on, and OUI is lost
dpcd_set_source_specific_data(link);
+ if (link->dpcd_sink_ext_caps.raw != 0)
+ msleep(post_oui_delay);
skip_video_pattern = true;
@@ -2560,12 +2562,14 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool
struct dmcu *dmcu = dc->res_pool->dmcu;
struct dmub_psr *psr = dc->res_pool->psr;
+ link->psr_settings.psr_allow_active = allow_active;
+
if (psr != NULL && link->psr_settings.psr_feature_enabled)
psr->funcs->psr_enable(psr, allow_active);
else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled)
dmcu->funcs->set_psr_enable(dmcu, allow_active, wait);
-
- link->psr_settings.psr_allow_active = allow_active;
+ else
+ return false;
return true;
}
@@ -3101,6 +3105,9 @@ void core_link_enable_stream(
struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
enum dc_status status;
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
+ enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO;
+#endif
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
if (!IS_DIAG_DC(dc->ctx->dce_environment) &&
@@ -3134,6 +3141,11 @@ void core_link_enable_stream(
pipe_ctx->stream->link->link_state_valid = true;
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
+ if (pipe_ctx->stream_res.tg->funcs->set_out_mux)
+ pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest);
+#endif
+
if (dc_is_dvi_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute(
pipe_ctx->stream_res.stream_enc,
@@ -3216,6 +3228,15 @@ void core_link_enable_stream(
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
COLOR_DEPTH_UNDEFINED);
+ /* This second call is needed to reconfigure the DIG
+ * as a workaround for the incorrect value being applied
+ * from transmitter control.
+ */
+ if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
+ stream->link->link_enc->funcs->setup(
+ stream->link->link_enc,
+ pipe_ctx->stream->signal);
+
dc->hwss.enable_stream(pipe_ctx);
/* Set DPS PPS SDP (AKA "info frames") */
@@ -3261,16 +3282,15 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
dc_is_virtual_signal(pipe_ctx->stream->signal))
return;
- if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+ if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
core_link_set_avmute(pipe_ctx, true);
}
+ dc->hwss.blank_stream(pipe_ctx);
#if defined(CONFIG_DRM_AMD_DC_HDCP)
update_psp_stream_config(pipe_ctx, true);
#endif
- dc->hwss.blank_stream(pipe_ctx);
-
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
deallocate_mst_payload(pipe_ctx);
@@ -3298,9 +3318,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
write_i2c_redriver_setting(pipe_ctx, false);
}
}
- dc->hwss.disable_stream(pipe_ctx);
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
+
+ dc->hwss.disable_stream(pipe_ctx);
+
if (pipe_ctx->stream->timing.flags.DSC) {
if (dc_is_dp_signal(pipe_ctx->stream->signal))
dp_set_dsc_enable(pipe_ctx, false);