diff options
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.c | 54 |
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); |