@@ -3305,6 +3305,7 @@ void core_link_enable_stream(
{
struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
+ struct dc_link *link = stream->sink->link;
enum dc_status status;
#if defined(CONFIG_DRM_AMD_DC_DCN)
enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO;
@@ -3333,6 +3334,9 @@ void core_link_enable_stream(
stream->use_vsc_sdp_for_colorimetry,
stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
+
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute(
pipe_ctx->stream_res.stream_enc,
@@ -3368,6 +3372,9 @@ void core_link_enable_stream(
resource_build_info_frame(pipe_ctx);
dc->hwss.update_info_frame(pipe_ctx);
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
+
/* Do not touch link on seamless boot optimization. */
if (pipe_ctx->stream->apply_seamless_boot_optimization) {
pipe_ctx->stream->dpms_off = false;
@@ -1810,8 +1810,11 @@ bool perform_link_training_with_retries(
/* We need to do this before the link training to ensure the idle pattern in SST
* mode will be sent right after the link training
*/
- link_enc->funcs->connect_dig_be_to_fe(link_enc,
+ if (dp_get_link_encoding_format(¤t_setting) == DP_8b_10b_ENCODING) {
+ link_enc->funcs->connect_dig_be_to_fe(link_enc,
pipe_ctx->stream_res.stream_enc->id, true);
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE);
+ }
for (j = 0; j < attempts; ++j) {
@@ -4397,7 +4400,7 @@ bool dc_link_dp_set_test_pattern(
* MuteAudioEndpoint(pPathMode->pDisplayPath, true);
*/
/* Blank stream */
- pipes->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
+ pipes->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);
}
dp_set_hw_test_pattern(link, test_pattern,
@@ -61,6 +61,13 @@ void dp_receiver_power_ctrl(struct dc_link *link, bool on)
sizeof(state));
}
+void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)
+{
+ if (link->dc->debug.enable_driver_sequence_debug)
+ core_link_write_dpcd(link, DP_SOURCE_SEQUENCE,
+ &dp_test_mode, sizeof(dp_test_mode));
+}
+
void dp_enable_link_phy(
struct dc_link *link,
enum signal_type signal,
@@ -132,6 +139,7 @@ void dp_enable_link_phy(
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);
}
@@ -233,6 +241,8 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
dmcu->funcs->unlock_phy(dmcu);
}
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
+
/* Clear current link setting.*/
memset(&link->cur_link_settings, 0,
sizeof(link->cur_link_settings));
@@ -320,6 +330,7 @@ void dp_set_hw_test_pattern(
pattern_param.dp_panel_mode = dp_get_panel_mode(link);
encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
}
void dp_retrain_link_dp_test(struct dc_link *link,
@@ -338,7 +349,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,
pipes[i].stream->link == link) {
udelay(100);
- pipes[i].stream_res.stream_enc->funcs->dp_blank(
+ pipes[i].stream_res.stream_enc->funcs->dp_blank(link,
pipes[i].stream_res.stream_enc);
/* disable any test pattern that might be active */
@@ -634,6 +634,7 @@ struct dc_debug_options {
bool force_enable_edp_fec;
/* FEC/PSR1 sequence enable delay in 100us */
uint8_t fec_enable_delay_in100us;
+ bool enable_driver_sequence_debug;
#if defined(CONFIG_DRM_AMD_DC_DCN)
bool disable_z10;
bool enable_sw_cntl_psr;
@@ -919,6 +919,7 @@ static void dce110_stream_encoder_stop_dp_info_packets(
}
static void dce110_stream_encoder_dp_blank(
+ struct dc_link *link,
struct stream_encoder *enc)
{
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
@@ -967,6 +968,7 @@ static void dce110_stream_encoder_dp_blank(
/* output video stream to link encoder */
static void dce110_stream_encoder_dp_unblank(
+ struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
{
@@ -57,7 +57,8 @@
#include "audio.h"
#include "reg_helper.h"
#include "panel_cntl.h"
-
+#include "inc/link_dpcd.h"
+#include "dpcd_defs.h"
/* include DCE11 register header files */
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
@@ -1113,6 +1114,9 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
if (pipe_ctx->stream_res.audio)
pipe_ctx->stream_res.audio->enabled = true;
}
+
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM);
}
void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
@@ -1151,6 +1155,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
* stream->stream_engine_id);
*/
}
+
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM);
}
void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
@@ -1177,6 +1184,8 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.stream_enc->id,
false);
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE);
}
void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
@@ -1192,7 +1201,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
params.link_settings.link_rate = link_settings->link_rate;
if (dc_is_dp_signal(pipe_ctx->stream->signal))
- pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
+ pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms);
if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
hws->funcs.edp_backlight_control(link, true);
@@ -1211,7 +1220,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
}
if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
- pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
+ pipe_ctx->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);
if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) {
/*
@@ -1436,6 +1445,7 @@ static enum dc_status apply_single_controller_ctx_to_hw(
struct dc *dc)
{
struct dc_stream_state *stream = pipe_ctx->stream;
+ struct dc_link *link = stream->link;
struct drr_params params = {0};
unsigned int event_triggers = 0;
struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
@@ -1499,6 +1509,9 @@ static enum dc_status apply_single_controller_ctx_to_hw(
pipe_ctx->stream_res.stream_enc,
pipe_ctx->stream_res.tg->inst);
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG);
+
pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
pipe_ctx->stream_res.opp,
COLOR_SPACE_YCBCR601,
@@ -1543,7 +1556,7 @@ static void power_down_encoders(struct dc *dc)
* hurt for non-DP
*/
for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
- dc->res_pool->stream_enc[i]->funcs->dp_blank(
+ dc->res_pool->stream_enc[i]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[i]);
}
@@ -1424,7 +1424,7 @@ void dcn10_init_hw(struct dc *dc)
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
if (fe == dc->res_pool->stream_enc[j]->id) {
- dc->res_pool->stream_enc[j]->funcs->dp_blank(
+ dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[j]);
break;
}
@@ -3613,7 +3613,7 @@ void dcn10_unblank_stream(struct pipe_ctx *pipe_ctx,
if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
if (params.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
params.timing.pix_clk_100hz /= 2;
- pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
+ pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms);
}
if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
@@ -29,6 +29,8 @@
#include "dcn10_stream_encoder.h"
#include "reg_helper.h"
#include "hw_shared.h"
+#include "inc/link_dpcd.h"
+#include "dpcd_defs.h"
#define DC_LOGGER \
enc1->base.ctx->logger
@@ -884,6 +886,7 @@ void enc1_stream_encoder_stop_dp_info_packets(
}
void enc1_stream_encoder_dp_blank(
+ struct dc_link *link,
struct stream_encoder *enc)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
@@ -914,6 +917,8 @@ void enc1_stream_encoder_dp_blank(
/* disable DP stream */
REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM);
+
/* the encoder stops sending the video stream
* at the start of the vertical blanking.
* Poll for DP_VID_STREAM_STATUS == 0
@@ -930,10 +935,13 @@ void enc1_stream_encoder_dp_blank(
*/
REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true);
+
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET);
}
/* output video stream to link encoder */
void enc1_stream_encoder_dp_unblank(
+ struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
{
@@ -1000,6 +1008,8 @@ void enc1_stream_encoder_dp_unblank(
*/
REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
+
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM);
}
void enc1_stream_encoder_set_avmute(
@@ -627,9 +627,11 @@ void enc1_stream_encoder_stop_dp_info_packets(
struct stream_encoder *enc);
void enc1_stream_encoder_dp_blank(
+ struct dc_link *link,
struct stream_encoder *enc);
void enc1_stream_encoder_dp_unblank(
+ struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param);
@@ -52,6 +52,8 @@
#include "dc_dmub_srv.h"
#include "dce/dmub_hw_lock_mgr.h"
#include "hw_sequencer.h"
+#include "inc/link_dpcd.h"
+#include "dpcd_defs.h"
#define DC_LOGGER_INIT(logger)
@@ -2140,7 +2142,7 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
params.timing.pix_clk_100hz /= 2;
pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1);
- pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
+ pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms);
}
if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
@@ -2383,6 +2385,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
pipe_ctx->stream_res.stream_enc->id, true);
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE);
+
if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) {
if (link->dc->hwss.program_dmdata_engine)
link->dc->hwss.program_dmdata_engine(pipe_ctx);
@@ -2390,6 +2395,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
link->dc->hwss.update_info_frame(pipe_ctx);
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
+
/* enable early control to avoid corruption on DP monitor*/
active_total_with_borders =
timing->h_addressable
@@ -29,6 +29,8 @@
#include "dcn20_stream_encoder.h"
#include "reg_helper.h"
#include "hw_shared.h"
+#include "inc/link_dpcd.h"
+#include "dpcd_defs.h"
#define DC_LOGGER \
enc1->base.ctx->logger
@@ -444,6 +446,7 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
}
void enc2_stream_encoder_dp_unblank(
+ struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
{
@@ -522,6 +525,8 @@ void enc2_stream_encoder_dp_unblank(
*/
REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
+
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM);
}
static void enc2_dp_set_odm_combine(
@@ -104,6 +104,7 @@ void enc2_stream_encoder_dp_set_stream_attribute(
uint32_t enable_sdp_splitting);
void enc2_stream_encoder_dp_unblank(
+ struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param);
@@ -559,7 +559,7 @@ void dcn30_init_hw(struct dc *dc)
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
if (fe == dc->res_pool->stream_enc[j]->id) {
- dc->res_pool->stream_enc[j]->funcs->dp_blank(
+ dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[j]);
break;
}
@@ -197,7 +197,7 @@ void dcn31_init_hw(struct dc *dc)
for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
if (fe == dc->res_pool->stream_enc[j]->id) {
- dc->res_pool->stream_enc[j]->funcs->dp_blank(
+ dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
dc->res_pool->stream_enc[j]);
break;
}
@@ -165,9 +165,11 @@ struct stream_encoder_funcs {
struct stream_encoder *enc);
void (*dp_blank)(
+ struct dc_link *link,
struct stream_encoder *enc);
void (*dp_unblank)(
+ struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param);
@@ -37,6 +37,7 @@ void dp_enable_link_phy(
const struct dc_link_settings *link_settings);
void dp_receiver_power_ctrl(struct dc_link *link, bool on);
+void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode);
void edp_add_delay_for_T9(struct dc_link *link);
bool edp_receiver_ready_T9(struct dc_link *link);
bool edp_receiver_ready_T7(struct dc_link *link);
@@ -69,9 +69,11 @@ static void virtual_stream_encoder_stop_dp_info_packets(
struct stream_encoder *enc) {}
static void virtual_stream_encoder_dp_blank(
+ struct dc_link *link,
struct stream_encoder *enc) {}
static void virtual_stream_encoder_dp_unblank(
+ struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param) {}
@@ -149,6 +149,7 @@ enum dpcd_psr_sink_states {
PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7,
};
+#define DP_SOURCE_SEQUENCE 0x30c
#define DP_SOURCE_TABLE_REVISION 0x310
#define DP_SOURCE_PAYLOAD_SIZE 0x311
#define DP_SOURCE_SINK_CAP 0x317
@@ -152,6 +152,22 @@ enum dp_panel_mode {
DP_PANEL_MODE_SPECIAL
};
+enum dpcd_source_sequence {
+ DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG = 1, /*done in apply_single_controller_ctx_to_hw */
+ DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR, /*done in core_link_enable_stream */
+ DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME, /*done in core_link_enable_stream/dcn20_enable_stream */
+ DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE, /*done in perform_link_training_with_retries/dcn20_enable_stream */
+ DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY, /*done in dp_enable_link_phy */
+ DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN, /*done in dp_set_hw_test_pattern */
+ DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM, /*done in dce110_enable_audio_stream */
+ DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM, /*done in enc1_stream_encoder_dp_unblank */
+ DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM, /*done in enc1_stream_encoder_dp_blank */
+ DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET, /*done in enc1_stream_encoder_dp_blank */
+ DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM, /*done in dce110_disable_audio_stream */
+ DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY, /*done in dp_disable_link_phy */
+ DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE, /*done in dce110_disable_stream */
+};
+
/* DPCD_ADDR_TRAINING_LANEx_SET registers value */
union dpcd_training_lane_set {
struct {