This reverts commit "Revert "Add DPCD writes at key points" ".
The following patch will fix the system hang issue.
v2: squash in indentation warning fix
Signed-off-by: Leo (Hanghong) Ma <hanghong.ma@amd.com>
Acked-by: Mikita Lipski <mikita.lipski@amd.com>
Reviewed-by: Aric Cyr <aric.cyr@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
{
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;
stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
#endif
+ 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,
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;
/* 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
*/
-#if defined(CONFIG_DRM_AMD_DC_DCN)
- if (dp_get_link_encoding_format(¤t_setting) == DP_8b_10b_ENCODING)
-#endif
+ 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) {
* 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,
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,
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);
}
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));
#else
encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
#endif
+ dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
#undef DC_LOGGER
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 */
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;
}
static void dce110_stream_encoder_dp_blank(
+ struct dc_link *link,
struct stream_encoder *enc)
{
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
/* 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)
{
#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"
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)
* 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)
pipe_ctx->stream_res.stream_enc->id,
false);
#endif
-
+ 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,
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);
#else
if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
#endif
- 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)) {
/*
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;
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,
* 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]);
}
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;
}
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) {
#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
}
void enc1_stream_encoder_dp_blank(
+ struct dc_link *link,
struct stream_encoder *enc)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
/* 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
*/
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)
{
*/
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(
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);
#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)
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) {
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);
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
#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
}
void enc2_stream_encoder_dp_unblank(
+ struct dc_link *link,
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
{
*/
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(
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);
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;
}
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;
}
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);
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);
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) {}
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
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 {