Commit f01ee019 authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher

drm/amd/display: Add DP 2.0 SST DC Support

1. Retrieve 128/132b link cap.
2. 128/132b link training and payload allocation.
3. UHBR10 link rate support.

[squash in warning fixes - Alex]
Signed-off-by: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 5a2730fc
...@@ -751,3 +751,11 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream) ...@@ -751,3 +751,11 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream)
&new_downspread.raw, &new_downspread.raw,
sizeof(new_downspread)); sizeof(new_downspread));
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz)
{
// FPGA programming for this clock in diags framework that
// needs to go through dm layer, therefore leave dummy interace here
}
#endif
\ No newline at end of file
...@@ -255,6 +255,24 @@ static bool create_links( ...@@ -255,6 +255,24 @@ static bool create_links(
goto failed_alloc; goto failed_alloc;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) &&
dc->caps.dp_hpo &&
link->dc->res_pool->res_cap->num_hpo_dp_link_encoder > 0) {
/* FPGA case - Allocate HPO DP link encoder */
if (i < link->dc->res_pool->res_cap->num_hpo_dp_link_encoder) {
link->hpo_dp_link_enc = link->dc->res_pool->hpo_dp_link_enc[i];
if (link->hpo_dp_link_enc == NULL) {
BREAK_TO_DEBUGGER();
goto failed_alloc;
}
link->hpo_dp_link_enc->hpd_source = link->link_enc->hpd_source;
link->hpo_dp_link_enc->transmitter = link->link_enc->transmitter;
}
}
#endif
link->link_status.dpcd_caps = &link->dpcd_caps; link->link_status.dpcd_caps = &link->dpcd_caps;
enc_init.ctx = dc->ctx; enc_init.ctx = dc->ctx;
......
...@@ -64,6 +64,31 @@ ...@@ -64,6 +64,31 @@
/******************************************************************************* /*******************************************************************************
* Private functions * Private functions
******************************************************************************/ ******************************************************************************/
#if defined(CONFIG_DRM_AMD_DC_DCN)
static bool add_dp_hpo_link_encoder_to_link(struct dc_link *link)
{
struct hpo_dp_link_encoder *enc = resource_get_unused_hpo_dp_link_encoder(
link->dc->res_pool);
if (!link->hpo_dp_link_enc && enc) {
link->hpo_dp_link_enc = enc;
link->hpo_dp_link_enc->transmitter = link->link_enc->transmitter;
link->hpo_dp_link_enc->hpd_source = link->link_enc->hpd_source;
}
return (link->hpo_dp_link_enc != NULL);
}
static void remove_dp_hpo_link_encoder_from_link(struct dc_link *link)
{
if (link->hpo_dp_link_enc) {
link->hpo_dp_link_enc->hpd_source = HPD_SOURCEID_UNKNOWN;
link->hpo_dp_link_enc->transmitter = TRANSMITTER_UNKNOWN;
link->hpo_dp_link_enc = NULL;
}
}
#endif
static void dc_link_destruct(struct dc_link *link) static void dc_link_destruct(struct dc_link *link)
{ {
int i; int i;
...@@ -91,6 +116,12 @@ static void dc_link_destruct(struct dc_link *link) ...@@ -91,6 +116,12 @@ static void dc_link_destruct(struct dc_link *link)
link->link_enc->funcs->destroy(&link->link_enc); link->link_enc->funcs->destroy(&link->link_enc);
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (link->hpo_dp_link_enc) {
remove_dp_hpo_link_encoder_from_link(link);
}
#endif
if (link->local_sink) if (link->local_sink)
dc_sink_release(link->local_sink); dc_sink_release(link->local_sink);
...@@ -928,6 +959,11 @@ static bool dc_link_detect_helper(struct dc_link *link, ...@@ -928,6 +959,11 @@ static bool dc_link_detect_helper(struct dc_link *link,
return false; return false;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING)
add_dp_hpo_link_encoder_to_link(link);
#endif
if (link->type == dc_connection_mst_branch) { if (link->type == dc_connection_mst_branch) {
LINK_INFO("link=%d, mst branch is now Connected\n", LINK_INFO("link=%d, mst branch is now Connected\n",
link->link_index); link->link_index);
...@@ -1173,6 +1209,11 @@ static bool dc_link_detect_helper(struct dc_link *link, ...@@ -1173,6 +1209,11 @@ static bool dc_link_detect_helper(struct dc_link *link,
sizeof(link->mst_stream_alloc_table.stream_allocations)); sizeof(link->mst_stream_alloc_table.stream_allocations));
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING)
reset_dp_hpo_stream_encoders_for_link(link);
#endif
link->type = dc_connection_none; link->type = dc_connection_none;
sink_caps.signal = SIGNAL_TYPE_NONE; sink_caps.signal = SIGNAL_TYPE_NONE;
/* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk /* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk
...@@ -1549,6 +1590,9 @@ static bool dc_link_construct(struct dc_link *link, ...@@ -1549,6 +1590,9 @@ static bool dc_link_construct(struct dc_link *link,
} }
DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C); DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
#if defined(CONFIG_DRM_AMD_DC_DCN)
DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
#endif
/* Update link encoder tracking variables. These are used for the dynamic /* Update link encoder tracking variables. These are used for the dynamic
* assignment of link encoders to streams. * assignment of link encoders to streams.
...@@ -1741,17 +1785,36 @@ static enum dc_status enable_link_dp(struct dc_state *state, ...@@ -1741,17 +1785,36 @@ static enum dc_status enable_link_dp(struct dc_state *state,
/* get link settings for video mode timing */ /* get link settings for video mode timing */
decide_link_settings(stream, &link_settings); decide_link_settings(stream, &link_settings);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING &&
pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
dp_enable_mst_on_sink(link, true);
}
#endif
if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) { if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {
/*in case it is not on*/ /*in case it is not on*/
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);
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING) {
/* TODO - DP2.0 HW: calculate 32 symbol clock for HPO encoder */
} else {
pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =
link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
if (state->clk_mgr && !apply_seamless_boot_optimization)
state->clk_mgr->funcs->update_clocks(state->clk_mgr,
state, false);
}
#else
pipe_ctx->stream_res.pix_clk_params.requested_sym_clk = pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =
link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
if (state->clk_mgr && !apply_seamless_boot_optimization) if (state->clk_mgr && !apply_seamless_boot_optimization)
state->clk_mgr->funcs->update_clocks(state->clk_mgr, state->clk_mgr->funcs->update_clocks(state->clk_mgr,
state, false); state, false);
#endif
// during mode switch we do DP_SET_POWER off then on, and OUI is lost // during mode switch we do DP_SET_POWER off then on, and OUI is lost
dpcd_set_source_specific_data(link); dpcd_set_source_specific_data(link);
...@@ -1780,7 +1843,12 @@ static enum dc_status enable_link_dp(struct dc_state *state, ...@@ -1780,7 +1843,12 @@ static enum dc_status enable_link_dp(struct dc_state *state,
else else
fec_enable = true; fec_enable = true;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING)
dp_set_fec_enable(link, fec_enable);
#else
dp_set_fec_enable(link, fec_enable); dp_set_fec_enable(link, fec_enable);
#endif
// during mode set we do DP_SET_POWER off then on, aux writes are lost // during mode set we do DP_SET_POWER off then on, aux writes are lost
if (link->dpcd_sink_ext_caps.bits.oled == 1 || if (link->dpcd_sink_ext_caps.bits.oled == 1 ||
...@@ -2284,6 +2352,9 @@ static void disable_link(struct dc_link *link, enum signal_type signal) ...@@ -2284,6 +2352,9 @@ static void disable_link(struct dc_link *link, enum signal_type signal)
if (dc_is_dp_signal(signal)) { if (dc_is_dp_signal(signal)) {
/* SST DP, eDP */ /* SST DP, eDP */
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dc_link_settings link_settings = link->cur_link_settings;
#endif
if (dc_is_dp_sst_signal(signal)) if (dc_is_dp_sst_signal(signal))
dp_disable_link_phy(link, signal); dp_disable_link_phy(link, signal);
else else
...@@ -2291,9 +2362,16 @@ static void disable_link(struct dc_link *link, enum signal_type signal) ...@@ -2291,9 +2362,16 @@ static void disable_link(struct dc_link *link, enum signal_type signal)
if (dc_is_dp_sst_signal(signal) || if (dc_is_dp_sst_signal(signal) ||
link->mst_stream_alloc_table.stream_count == 0) { link->mst_stream_alloc_table.stream_count == 0) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) {
dp_set_fec_enable(link, false); dp_set_fec_enable(link, false);
dp_set_fec_ready(link, false); dp_set_fec_ready(link, false);
} }
#else
dp_set_fec_enable(link, false);
dp_set_fec_ready(link, false);
#endif
}
} else { } else {
if (signal != SIGNAL_TYPE_VIRTUAL) if (signal != SIGNAL_TYPE_VIRTUAL)
link->link_enc->funcs->disable_output(link->link_enc, signal); link->link_enc->funcs->disable_output(link->link_enc, signal);
...@@ -2475,9 +2553,14 @@ static bool dp_active_dongle_validate_timing( ...@@ -2475,9 +2553,14 @@ static bool dp_active_dongle_validate_timing(
break; break;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dpcd_caps->dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER &&
dongle_caps->extendedCapValid == true) {
#else
if (dpcd_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER || if (dpcd_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER ||
dongle_caps->extendedCapValid == false) dongle_caps->extendedCapValid == false)
return true; return true;
#endif
/* Check Pixel Encoding */ /* Check Pixel Encoding */
switch (timing->pixel_encoding) { switch (timing->pixel_encoding) {
...@@ -2520,6 +2603,87 @@ static bool dp_active_dongle_validate_timing( ...@@ -2520,6 +2603,87 @@ static bool dp_active_dongle_validate_timing(
if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10)) if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
return false; return false;
#if defined(CONFIG_DRM_AMD_DC_DCN)
}
if (dongle_caps->dfp_cap_ext.supported) {
if (dongle_caps->dfp_cap_ext.max_pixel_rate_in_mps < (timing->pix_clk_100hz / 10000))
return false;
if (dongle_caps->dfp_cap_ext.max_video_h_active_width < timing->h_addressable)
return false;
if (dongle_caps->dfp_cap_ext.max_video_v_active_height < timing->v_addressable)
return false;
if (timing->pixel_encoding == PIXEL_ENCODING_RGB) {
if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
return false;
if (timing->display_color_depth == COLOR_DEPTH_666 &&
!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_6bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_888 &&
!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_8bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_10bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_12bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_16bpc)
return false;
} else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) {
if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
return false;
if (timing->display_color_depth == COLOR_DEPTH_888 &&
!dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_8bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
!dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_10bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
!dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_12bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
!dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_16bpc)
return false;
} else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
return false;
if (timing->display_color_depth == COLOR_DEPTH_888 &&
!dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_8bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
!dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_10bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
!dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_12bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
!dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_16bpc)
return false;
} else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
return false;
if (timing->display_color_depth == COLOR_DEPTH_888 &&
!dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_8bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
!dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_10bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
!dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_12bpc)
return false;
else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
!dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_16bpc)
return false;
}
}
#endif
return true; return true;
} }
...@@ -3016,6 +3180,107 @@ static void update_mst_stream_alloc_table( ...@@ -3016,6 +3180,107 @@ static void update_mst_stream_alloc_table(
link->mst_stream_alloc_table.stream_allocations[i] = link->mst_stream_alloc_table.stream_allocations[i] =
work_table[i]; work_table[i];
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
/*
* Payload allocation/deallocation for SST introduced in DP2.0
*/
enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, bool allocate)
{
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc;
struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc;
struct link_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp;
DC_LOGGER_INIT(link->ctx->logger);
/* slot X.Y for SST payload deallocate */
if (!allocate) {
avg_time_slots_per_mtp = dc_fixpt_from_int(0);
DC_LOG_DP2("SST Update Payload: set_throttled_vcp_size slot X.Y for SST stream"
"X: %d "
"Y: %d",
dc_fixpt_floor(
avg_time_slots_per_mtp),
dc_fixpt_ceil(
dc_fixpt_shl(
dc_fixpt_sub_int(
avg_time_slots_per_mtp,
dc_fixpt_floor(
avg_time_slots_per_mtp)),
26)));
hpo_dp_link_encoder->funcs->set_throttled_vcp_size(
hpo_dp_link_encoder,
hpo_dp_stream_encoder->inst,
avg_time_slots_per_mtp);
}
/* calculate VC payload and update branch with new payload allocation table*/
if (!dpcd_write_128b_132b_sst_payload_allocation_table(
stream,
link,
&proposed_table,
allocate)) {
DC_LOG_ERROR("SST Update Payload: Failed to update "
"allocation table for "
"pipe idx: %d\n",
pipe_ctx->pipe_idx);
}
proposed_table.stream_allocations[0].hpo_dp_stream_enc = hpo_dp_stream_encoder;
ASSERT(proposed_table.stream_count == 1);
//TODO - DP2.0 Logging: Instead of hpo_dp_stream_enc pointer, log instance id
DC_LOG_DP2("SST Update Payload: hpo_dp_stream_enc: %p "
"vcp_id: %d "
"slot_count: %d\n",
(void *) proposed_table.stream_allocations[0].hpo_dp_stream_enc,
proposed_table.stream_allocations[0].vcp_id,
proposed_table.stream_allocations[0].slot_count);
/* program DP source TX for payload */
hpo_dp_link_encoder->funcs->update_stream_allocation_table(
hpo_dp_link_encoder,
&proposed_table);
/* poll for ACT handled */
if (!dpcd_poll_for_allocation_change_trigger(link)) {
// Failures will result in blackscreen and errors logged
BREAK_TO_DEBUGGER();
}
/* slot X.Y for SST payload allocate */
if (allocate) {
avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
DC_LOG_DP2("SST Update Payload: "
"slot.X: %d "
"slot.Y: %d",
dc_fixpt_floor(
avg_time_slots_per_mtp),
dc_fixpt_ceil(
dc_fixpt_shl(
dc_fixpt_sub_int(
avg_time_slots_per_mtp,
dc_fixpt_floor(
avg_time_slots_per_mtp)),
26)));
hpo_dp_link_encoder->funcs->set_throttled_vcp_size(
hpo_dp_link_encoder,
hpo_dp_stream_encoder->inst,
avg_time_slots_per_mtp);
}
/* Always return DC_OK.
* If part of sequence fails, log failure(s) and show blackscreen
*/
return DC_OK;
}
#endif
/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table /* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
* because stream_encoder is not exposed to dm * because stream_encoder is not exposed to dm
...@@ -3203,6 +3468,11 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) ...@@ -3203,6 +3468,11 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA; config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA;
config.link_enc_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; config.link_enc_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A;
config.phy_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; config.phy_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A;
if (is_dp_128b_132b_signal(pipe_ctx)) {
config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0;
config.link_enc_idx = pipe_ctx->stream->link->hpo_dp_link_enc->inst;
config.dp2_enabled = 1;
}
#endif #endif
config.dpms_off = dpms_off; config.dpms_off = dpms_off;
config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context; config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context;
...@@ -3214,6 +3484,88 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) ...@@ -3214,6 +3484,88 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
} }
#endif #endif
#if defined(CONFIG_DRM_AMD_DC_DCN)
static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pipe_ctx *pipe_ctx)
{
struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
struct link_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp;
uint8_t req_slot_count = 0;
uint8_t vc_id = 1; /// VC ID always 1 for SST
struct dc_link_settings link_settings = {0};
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
decide_link_settings(stream, &link_settings);
stream->link->cur_link_settings = link_settings;
/* Enable clock, Configure lane count, and Enable Link Encoder*/
enable_dp_hpo_output(stream->link, &stream->link->cur_link_settings);
#ifdef DIAGS_BUILD
/* Workaround for FPGA HPO capture DP link data:
* HPO capture will set link to active mode
* This workaround is required to get a capture from start of frame
*/
if (!dc->debug.fpga_hpo_capture_en) {
struct encoder_set_dp_phy_pattern_param params = {0};
params.dp_phy_pattern = DP_TEST_PATTERN_VIDEO_MODE;
/* Set link active */
stream->link->hpo_dp_link_enc->funcs->set_link_test_pattern(
stream->link->hpo_dp_link_enc,
&params);
}
#endif
/* Enable DP_STREAM_ENC */
dc->hwss.enable_stream(pipe_ctx);
/* Set DPS PPS SDP (AKA "info frames") */
if (pipe_ctx->stream->timing.flags.DSC) {
dp_set_dsc_pps_sdp(pipe_ctx, true);
}
/* Allocate Payload */
if ((stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) && (state->stream_count > 1)) {
// MST case
uint8_t i;
proposed_table.stream_count = state->stream_count;
for (i = 0; i < state->stream_count; i++) {
avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(state->streams[i], state->streams[i]->link);
req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
proposed_table.stream_allocations[i].slot_count = req_slot_count;
proposed_table.stream_allocations[i].vcp_id = i+1;
/* NOTE: This makes assumption that pipe_ctx index is same as stream index */
proposed_table.stream_allocations[i].hpo_dp_stream_enc = state->res_ctx.pipe_ctx[i].stream_res.hpo_dp_stream_enc;
}
} else {
// SST case
avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, stream->link);
req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
proposed_table.stream_count = 1; /// Always 1 stream for SST
proposed_table.stream_allocations[0].slot_count = req_slot_count;
proposed_table.stream_allocations[0].vcp_id = vc_id;
proposed_table.stream_allocations[0].hpo_dp_stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
}
stream->link->hpo_dp_link_enc->funcs->update_stream_allocation_table(
stream->link->hpo_dp_link_enc,
&proposed_table);
stream->link->hpo_dp_link_enc->funcs->set_throttled_vcp_size(
stream->link->hpo_dp_link_enc,
pipe_ctx->stream_res.hpo_dp_stream_enc->inst,
avg_time_slots_per_mtp);
dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings);
}
#endif
void core_link_enable_stream( void core_link_enable_stream(
struct dc_state *state, struct dc_state *state,
struct pipe_ctx *pipe_ctx) struct pipe_ctx *pipe_ctx)
...@@ -3230,7 +3582,12 @@ void core_link_enable_stream( ...@@ -3230,7 +3582,12 @@ void core_link_enable_stream(
dc_is_virtual_signal(pipe_ctx->stream->signal)) dc_is_virtual_signal(pipe_ctx->stream->signal))
return; return;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)
&& !is_dp_128b_132b_signal(pipe_ctx)) {
#else
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) { if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) {
#endif
stream->link->link_enc->funcs->setup( stream->link->link_enc->funcs->setup(
stream->link->link_enc, stream->link->link_enc,
pipe_ctx->stream->signal); pipe_ctx->stream->signal);
...@@ -3240,13 +3597,32 @@ void core_link_enable_stream( ...@@ -3240,13 +3597,32 @@ void core_link_enable_stream(
stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE);
} }
if (dc_is_dp_signal(pipe_ctx->stream->signal)) #if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx)) {
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->set_stream_attribute(
pipe_ctx->stream_res.hpo_dp_stream_enc,
&stream->timing,
stream->output_color_space,
stream->use_vsc_sdp_for_colorimetry,
stream->timing.flags.DSC,
false);
otg_out_dest = OUT_MUX_HPO_DP;
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(
pipe_ctx->stream_res.stream_enc,
&stream->timing,
stream->output_color_space,
stream->use_vsc_sdp_for_colorimetry,
stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
}
#else
pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(
pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.stream_enc,
&stream->timing, &stream->timing,
stream->output_color_space, stream->output_color_space,
stream->use_vsc_sdp_for_colorimetry, stream->use_vsc_sdp_for_colorimetry,
stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
#endif
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) 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->funcs->hdmi_set_stream_attribute(
...@@ -3357,7 +3733,12 @@ void core_link_enable_stream( ...@@ -3357,7 +3733,12 @@ void core_link_enable_stream(
* as a workaround for the incorrect value being applied * as a workaround for the incorrect value being applied
* from transmitter control. * from transmitter control.
*/ */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||
is_dp_128b_132b_signal(pipe_ctx)))
#else
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
#endif
stream->link->link_enc->funcs->setup( stream->link->link_enc->funcs->setup(
stream->link->link_enc, stream->link->link_enc,
pipe_ctx->stream->signal); pipe_ctx->stream->signal);
...@@ -3375,6 +3756,11 @@ void core_link_enable_stream( ...@@ -3375,6 +3756,11 @@ void core_link_enable_stream(
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
dc_link_allocate_mst_payload(pipe_ctx); dc_link_allocate_mst_payload(pipe_ctx);
#if defined(CONFIG_DRM_AMD_DC_DCN)
else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
is_dp_128b_132b_signal(pipe_ctx))
dc_link_update_sst_payload(pipe_ctx, true);
#endif
dc->hwss.unblank_stream(pipe_ctx, dc->hwss.unblank_stream(pipe_ctx,
&pipe_ctx->stream->link->cur_link_settings); &pipe_ctx->stream->link->cur_link_settings);
...@@ -3391,6 +3777,11 @@ void core_link_enable_stream( ...@@ -3391,6 +3777,11 @@ void core_link_enable_stream(
dc->hwss.enable_audio_stream(pipe_ctx); dc->hwss.enable_audio_stream(pipe_ctx);
} else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) } else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx)) {
fpga_dp_hpo_enable_link_and_stream(state, pipe_ctx);
}
#endif
if (dc_is_dp_signal(pipe_ctx->stream->signal) || if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
dc_is_virtual_signal(pipe_ctx->stream->signal)) dc_is_virtual_signal(pipe_ctx->stream->signal))
dp_set_dsc_enable(pipe_ctx, true); dp_set_dsc_enable(pipe_ctx, true);
...@@ -3426,6 +3817,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -3426,6 +3817,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
deallocate_mst_payload(pipe_ctx); deallocate_mst_payload(pipe_ctx);
#if defined(CONFIG_DRM_AMD_DC_DCN)
else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
is_dp_128b_132b_signal(pipe_ctx))
dc_link_update_sst_payload(pipe_ctx, false);
#endif
if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
struct ext_hdmi_settings settings = {0}; struct ext_hdmi_settings settings = {0};
...@@ -3452,14 +3848,39 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -3452,14 +3848,39 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
} }
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
!is_dp_128b_132b_signal(pipe_ctx)) {
/* In DP1.x SST mode, our encoder will go to TPS1
* when link is on but stream is off.
* Disabling link before stream will avoid exposing TPS1 pattern
* during the disable sequence as it will confuse some receivers
* state machine.
* In DP2 or MST mode, our encoder will stay video active
*/
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
dc->hwss.disable_stream(pipe_ctx);
} else {
dc->hwss.disable_stream(pipe_ctx);
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
}
#else
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
dc->hwss.disable_stream(pipe_ctx); dc->hwss.disable_stream(pipe_ctx);
#endif
if (pipe_ctx->stream->timing.flags.DSC) { if (pipe_ctx->stream->timing.flags.DSC) {
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (dc_is_dp_signal(pipe_ctx->stream->signal))
dp_set_dsc_enable(pipe_ctx, false); dp_set_dsc_enable(pipe_ctx, false);
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx)) {
if (pipe_ctx->stream_res.tg->funcs->set_out_mux)
pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO);
}
#endif
} }
void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
...@@ -3592,6 +4013,13 @@ void dc_link_set_preferred_training_settings(struct dc *dc, ...@@ -3592,6 +4013,13 @@ void dc_link_set_preferred_training_settings(struct dc *dc,
if (link_setting != NULL) { if (link_setting != NULL) {
link->preferred_link_setting = *link_setting; link->preferred_link_setting = *link_setting;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(link_setting) ==
DP_128b_132b_ENCODING && !link->hpo_dp_link_enc) {
if (!add_dp_hpo_link_encoder_to_link(link))
memset(&link->preferred_link_setting, 0, sizeof(link->preferred_link_setting));
}
#endif
} else { } else {
link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN; link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN;
link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN; link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
...@@ -3633,6 +4061,38 @@ uint32_t dc_link_bandwidth_kbps( ...@@ -3633,6 +4061,38 @@ uint32_t dc_link_bandwidth_kbps(
const struct dc_link *link, const struct dc_link *link,
const struct dc_link_settings *link_setting) const struct dc_link_settings *link_setting)
{ {
#if defined(CONFIG_DRM_AMD_DC_DCN)
uint32_t total_data_bw_efficiency_x10000 = 0;
uint32_t link_rate_per_lane_kbps = 0;
switch (dp_get_link_encoding_format(link_setting)) {
case DP_8b_10b_ENCODING:
/* For 8b/10b encoding:
* link rate is defined in the unit of LINK_RATE_REF_FREQ_IN_KHZ per DP byte per lane.
* data bandwidth efficiency is 80% with additional 3% overhead if FEC is supported.
*/
link_rate_per_lane_kbps = link_setting->link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS_PER_DP_BYTE;
total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_8b_10b_x10000;
if (dc_link_should_enable_fec(link)) {
total_data_bw_efficiency_x10000 /= 100;
total_data_bw_efficiency_x10000 *= DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100;
}
break;
case DP_128b_132b_ENCODING:
/* For 128b/132b encoding:
* link rate is defined in the unit of 10mbps per lane.
* total data bandwidth efficiency is always 96.71%.
*/
link_rate_per_lane_kbps = link_setting->link_rate * 10000;
total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_128b_132b_x10000;
break;
default:
break;
}
/* overall effective link bandwidth = link rate per lane * lane count * total data bandwidth efficiency */
return link_rate_per_lane_kbps * link_setting->lane_count / 10000 * total_data_bw_efficiency_x10000;
#else
uint32_t link_bw_kbps = uint32_t link_bw_kbps =
link_setting->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; /* bytes per sec */ link_setting->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; /* bytes per sec */
...@@ -3663,9 +4123,9 @@ uint32_t dc_link_bandwidth_kbps( ...@@ -3663,9 +4123,9 @@ uint32_t dc_link_bandwidth_kbps(
long long fec_link_bw_kbps = link_bw_kbps * 970LL; long long fec_link_bw_kbps = link_bw_kbps * 970LL;
link_bw_kbps = (uint32_t)(div64_s64(fec_link_bw_kbps, 1000LL)); link_bw_kbps = (uint32_t)(div64_s64(fec_link_bw_kbps, 1000LL));
} }
return link_bw_kbps; return link_bw_kbps;
#endif
} }
const struct dc_link_settings *dc_link_get_link_cap( const struct dc_link_settings *dc_link_get_link_cap(
......
...@@ -39,6 +39,43 @@ enum { ...@@ -39,6 +39,43 @@ enum {
POST_LT_ADJ_REQ_TIMEOUT = 200 POST_LT_ADJ_REQ_TIMEOUT = 200
}; };
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dp_lt_fallback_entry {
enum dc_lane_count lane_count;
enum dc_link_rate link_rate;
};
static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = {
/* This link training fallback array is ordered by
* link bandwidth from highest to lowest.
* DP specs makes it a normative policy to always
* choose the next highest link bandwidth during
* link training fallback.
*/
{LANE_COUNT_FOUR, LINK_RATE_UHBR20},
{LANE_COUNT_FOUR, LINK_RATE_UHBR13_5},
{LANE_COUNT_TWO, LINK_RATE_UHBR20},
{LANE_COUNT_FOUR, LINK_RATE_UHBR10},
{LANE_COUNT_TWO, LINK_RATE_UHBR13_5},
{LANE_COUNT_FOUR, LINK_RATE_HIGH3},
{LANE_COUNT_ONE, LINK_RATE_UHBR20},
{LANE_COUNT_TWO, LINK_RATE_UHBR10},
{LANE_COUNT_FOUR, LINK_RATE_HIGH2},
{LANE_COUNT_ONE, LINK_RATE_UHBR13_5},
{LANE_COUNT_TWO, LINK_RATE_HIGH3},
{LANE_COUNT_ONE, LINK_RATE_UHBR10},
{LANE_COUNT_TWO, LINK_RATE_HIGH2},
{LANE_COUNT_FOUR, LINK_RATE_HIGH},
{LANE_COUNT_ONE, LINK_RATE_HIGH3},
{LANE_COUNT_FOUR, LINK_RATE_LOW},
{LANE_COUNT_ONE, LINK_RATE_HIGH2},
{LANE_COUNT_TWO, LINK_RATE_HIGH},
{LANE_COUNT_TWO, LINK_RATE_LOW},
{LANE_COUNT_ONE, LINK_RATE_HIGH},
{LANE_COUNT_ONE, LINK_RATE_LOW},
};
#endif
static bool decide_fallback_link_setting( static bool decide_fallback_link_setting(
struct dc_link_settings initial_link_settings, struct dc_link_settings initial_link_settings,
struct dc_link_settings *current_link_setting, struct dc_link_settings *current_link_setting,
...@@ -52,8 +89,19 @@ static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link, ...@@ -52,8 +89,19 @@ static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
{ {
union training_aux_rd_interval training_rd_interval; union training_aux_rd_interval training_rd_interval;
uint32_t wait_in_micro_secs = 100; uint32_t wait_in_micro_secs = 100;
#if defined(CONFIG_DRM_AMD_DC_DCN)
memset(&training_rd_interval, 0, sizeof(training_rd_interval)); memset(&training_rd_interval, 0, sizeof(training_rd_interval));
if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
core_link_read_dpcd(
link,
DP_TRAINING_AUX_RD_INTERVAL,
(uint8_t *)&training_rd_interval,
sizeof(training_rd_interval));
if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
}
#else
core_link_read_dpcd( core_link_read_dpcd(
link, link,
DP_TRAINING_AUX_RD_INTERVAL, DP_TRAINING_AUX_RD_INTERVAL,
...@@ -61,6 +109,7 @@ static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link, ...@@ -61,6 +109,7 @@ static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
sizeof(training_rd_interval)); sizeof(training_rd_interval));
if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
#endif
return wait_in_micro_secs; return wait_in_micro_secs;
} }
...@@ -68,6 +117,36 @@ static uint32_t get_eq_training_aux_rd_interval( ...@@ -68,6 +117,36 @@ static uint32_t get_eq_training_aux_rd_interval(
struct dc_link *link, struct dc_link *link,
const struct dc_link_settings *link_settings) const struct dc_link_settings *link_settings)
{ {
#if defined(CONFIG_DRM_AMD_DC_DCN)
union training_aux_rd_interval training_rd_interval;
memset(&training_rd_interval, 0, sizeof(training_rd_interval));
if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
core_link_read_dpcd(
link,
DP_128b_132b_TRAINING_AUX_RD_INTERVAL,
(uint8_t *)&training_rd_interval,
sizeof(training_rd_interval));
} else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
core_link_read_dpcd(
link,
DP_TRAINING_AUX_RD_INTERVAL,
(uint8_t *)&training_rd_interval,
sizeof(training_rd_interval));
}
switch (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) {
case 0: return 400;
case 1: return 4000;
case 2: return 8000;
case 3: return 12000;
case 4: return 16000;
case 5: return 32000;
case 6: return 64000;
default: return 400;
}
#else
union training_aux_rd_interval training_rd_interval; union training_aux_rd_interval training_rd_interval;
uint32_t wait_in_micro_secs = 400; uint32_t wait_in_micro_secs = 400;
...@@ -87,13 +166,21 @@ static uint32_t get_eq_training_aux_rd_interval( ...@@ -87,13 +166,21 @@ static uint32_t get_eq_training_aux_rd_interval(
} }
return wait_in_micro_secs; return wait_in_micro_secs;
#endif
} }
void dp_wait_for_training_aux_rd_interval( void dp_wait_for_training_aux_rd_interval(
struct dc_link *link, struct dc_link *link,
uint32_t wait_in_micro_secs) uint32_t wait_in_micro_secs)
{ {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (wait_in_micro_secs > 16000)
msleep(wait_in_micro_secs/1000);
else
udelay(wait_in_micro_secs);
#else
udelay(wait_in_micro_secs); udelay(wait_in_micro_secs);
#endif
DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n", DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
__func__, __func__,
...@@ -121,6 +208,17 @@ enum dpcd_training_patterns ...@@ -121,6 +208,17 @@ enum dpcd_training_patterns
case DP_TRAINING_PATTERN_SEQUENCE_4: case DP_TRAINING_PATTERN_SEQUENCE_4:
dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4; dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
break; break;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case DP_128b_132b_TPS1:
dpcd_tr_pattern = DPCD_128b_132b_TPS1;
break;
case DP_128b_132b_TPS2:
dpcd_tr_pattern = DPCD_128b_132b_TPS2;
break;
case DP_128b_132b_TPS2_CDS:
dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS;
break;
#endif
case DP_TRAINING_PATTERN_VIDEOIDLE: case DP_TRAINING_PATTERN_VIDEOIDLE:
dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE; dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE;
break; break;
...@@ -159,13 +257,57 @@ static void dpcd_set_training_pattern( ...@@ -159,13 +257,57 @@ static void dpcd_set_training_pattern(
static enum dc_dp_training_pattern decide_cr_training_pattern( static enum dc_dp_training_pattern decide_cr_training_pattern(
const struct dc_link_settings *link_settings) const struct dc_link_settings *link_settings)
{ {
switch (dp_get_link_encoding_format(link_settings)) {
case DP_8b_10b_ENCODING:
default:
return DP_TRAINING_PATTERN_SEQUENCE_1; return DP_TRAINING_PATTERN_SEQUENCE_1;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case DP_128b_132b_ENCODING:
return DP_128b_132b_TPS1;
#endif
}
} }
static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link, static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
const struct dc_link_settings *link_settings) const struct dc_link_settings *link_settings)
{ {
struct link_encoder *link_enc; struct link_encoder *link_enc;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct encoder_feature_support *enc_caps;
struct dpcd_caps *rx_caps = &link->dpcd_caps;
enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
/* Access link encoder capability based on whether it is statically
* or dynamically assigned to a link.
*/
if (link->is_dig_mapping_flexible &&
link->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);
enc_caps = &link_enc->features;
switch (dp_get_link_encoding_format(link_settings)) {
case DP_8b_10b_ENCODING:
if (enc_caps->flags.bits.IS_TPS4_CAPABLE &&
rx_caps->max_down_spread.bits.TPS4_SUPPORTED)
pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
else if (enc_caps->flags.bits.IS_TPS3_CAPABLE &&
rx_caps->max_ln_count.bits.TPS3_SUPPORTED)
pattern = DP_TRAINING_PATTERN_SEQUENCE_3;
else
pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
break;
case DP_128b_132b_ENCODING:
pattern = DP_128b_132b_TPS2;
break;
default:
pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
break;
}
return pattern;
#else
enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2; enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2;
struct encoder_feature_support *features; struct encoder_feature_support *features;
struct dpcd_caps *dpcd_caps = &link->dpcd_caps; struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
...@@ -196,7 +338,38 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li ...@@ -196,7 +338,38 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li
return DP_TRAINING_PATTERN_SEQUENCE_3; return DP_TRAINING_PATTERN_SEQUENCE_3;
return DP_TRAINING_PATTERN_SEQUENCE_2; return DP_TRAINING_PATTERN_SEQUENCE_2;
#endif
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
static uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings)
{
uint8_t link_rate = 0;
enum dp_link_encoding encoding = dp_get_link_encoding_format(link_settings);
if (encoding == DP_128b_132b_ENCODING)
switch (link_settings->link_rate) {
case LINK_RATE_UHBR10:
link_rate = 0x1;
break;
case LINK_RATE_UHBR20:
link_rate = 0x2;
break;
case LINK_RATE_UHBR13_5:
link_rate = 0x4;
break;
default:
link_rate = 0;
break;
}
else if (encoding == DP_8b_10b_ENCODING)
link_rate = (uint8_t) link_settings->link_rate;
else
link_rate = 0;
return link_rate;
} }
#endif
enum dc_status dpcd_set_link_settings( enum dc_status dpcd_set_link_settings(
struct dc_link *link, struct dc_link *link,
...@@ -247,7 +420,11 @@ enum dc_status dpcd_set_link_settings( ...@@ -247,7 +420,11 @@ enum dc_status dpcd_set_link_settings(
status = core_link_write_dpcd(link, DP_LINK_RATE_SET, status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
&lt_settings->link_settings.link_rate_set, 1); &lt_settings->link_settings.link_rate_set, 1);
} else { } else {
#if defined(CONFIG_DRM_AMD_DC_DCN)
rate = get_dpcd_link_rate(&lt_settings->link_settings);
#else
rate = (uint8_t) (lt_settings->link_settings.link_rate); rate = (uint8_t) (lt_settings->link_settings.link_rate);
#endif
status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
} }
...@@ -289,6 +466,10 @@ uint8_t dc_dp_initialize_scrambling_data_symbols( ...@@ -289,6 +466,10 @@ uint8_t dc_dp_initialize_scrambling_data_symbols(
disable_scrabled_data_symbols = 1; disable_scrabled_data_symbols = 1;
break; break;
case DP_TRAINING_PATTERN_SEQUENCE_4: case DP_TRAINING_PATTERN_SEQUENCE_4:
#if defined(CONFIG_DRM_AMD_DC_DCN)
case DP_128b_132b_TPS1:
case DP_128b_132b_TPS2:
#endif
disable_scrabled_data_symbols = 0; disable_scrabled_data_symbols = 0;
break; break;
default: default:
...@@ -356,6 +537,13 @@ static void dpcd_set_lt_pattern_and_lane_settings( ...@@ -356,6 +537,13 @@ static void dpcd_set_lt_pattern_and_lane_settings(
for (lane = 0; lane < for (lane = 0; lane <
(uint32_t)(lt_settings->link_settings.lane_count); lane++) { (uint32_t)(lt_settings->link_settings.lane_count); lane++) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_128b_132b_ENCODING) {
dpcd_lane[lane].tx_ffe.PRESET_VALUE =
lt_settings->lane_settings[lane].FFE_PRESET.settings.level;
} else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_8b_10b_ENCODING) {
dpcd_lane[lane].bits.VOLTAGE_SWING_SET = dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
(uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING); (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
dpcd_lane[lane].bits.PRE_EMPHASIS_SET = dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
...@@ -368,6 +556,20 @@ static void dpcd_set_lt_pattern_and_lane_settings( ...@@ -368,6 +556,20 @@ static void dpcd_set_lt_pattern_and_lane_settings(
(lt_settings->lane_settings[lane].PRE_EMPHASIS == (lt_settings->lane_settings[lane].PRE_EMPHASIS ==
PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
} }
#else
dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
(uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
(uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS);
dpcd_lane[lane].bits.MAX_SWING_REACHED =
(lt_settings->lane_settings[lane].VOLTAGE_SWING ==
VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
(lt_settings->lane_settings[lane].PRE_EMPHASIS ==
PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
#endif
}
/* concatenate everything into one buffer*/ /* concatenate everything into one buffer*/
...@@ -380,6 +582,18 @@ static void dpcd_set_lt_pattern_and_lane_settings( ...@@ -380,6 +582,18 @@ static void dpcd_set_lt_pattern_and_lane_settings(
size_in_bytes); size_in_bytes);
if (is_repeater(link, offset)) { if (is_repeater(link, offset)) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_128b_132b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
" 0x%X TX_FFE_PRESET_VALUE = %x\n",
__func__,
offset,
dpcd_base_lt_offset,
dpcd_lane[0].tx_ffe.PRESET_VALUE);
else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_8b_10b_ENCODING)
#endif
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
" 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__, __func__,
...@@ -390,6 +604,16 @@ static void dpcd_set_lt_pattern_and_lane_settings( ...@@ -390,6 +604,16 @@ static void dpcd_set_lt_pattern_and_lane_settings(
dpcd_lane[0].bits.MAX_SWING_REACHED, dpcd_lane[0].bits.MAX_SWING_REACHED,
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
} else { } else {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_128b_132b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
__func__,
dpcd_base_lt_offset,
dpcd_lane[0].tx_ffe.PRESET_VALUE);
else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_8b_10b_ENCODING)
#endif
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__, __func__,
dpcd_base_lt_offset, dpcd_base_lt_offset,
...@@ -414,6 +638,15 @@ static void dpcd_set_lt_pattern_and_lane_settings( ...@@ -414,6 +638,15 @@ static void dpcd_set_lt_pattern_and_lane_settings(
(uint8_t *)(dpcd_lane), (uint8_t *)(dpcd_lane),
size_in_bytes); size_in_bytes);
#if defined(CONFIG_DRM_AMD_DC_DCN)
} else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_128b_132b_ENCODING) {
core_link_write_dpcd(
link,
dpcd_base_lt_offset,
dpcd_lt_buffer,
sizeof(dpcd_lt_buffer));
#endif
} else } else
/* write it all in (1 + number-of-lanes)-byte burst*/ /* write it all in (1 + number-of-lanes)-byte burst*/
core_link_write_dpcd( core_link_write_dpcd(
...@@ -484,6 +717,13 @@ void dp_update_drive_settings( ...@@ -484,6 +717,13 @@ void dp_update_drive_settings(
dest->lane_settings[lane].POST_CURSOR2 = src.lane_settings[lane].POST_CURSOR2; dest->lane_settings[lane].POST_CURSOR2 = src.lane_settings[lane].POST_CURSOR2;
else else
dest->lane_settings[lane].POST_CURSOR2 = *dest->post_cursor2; dest->lane_settings[lane].POST_CURSOR2 = *dest->post_cursor2;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dest->ffe_preset == NULL)
dest->lane_settings[lane].FFE_PRESET = src.lane_settings[lane].FFE_PRESET;
else
dest->lane_settings[lane].FFE_PRESET = *dest->ffe_preset;
#endif
} }
} }
...@@ -529,6 +769,10 @@ static void find_max_drive_settings( ...@@ -529,6 +769,10 @@ static void find_max_drive_settings(
lane_settings[0].PRE_EMPHASIS; lane_settings[0].PRE_EMPHASIS;
/*max_requested.postCursor2 = /*max_requested.postCursor2 =
* link_training_setting->laneSettings[0].postCursor2;*/ * link_training_setting->laneSettings[0].postCursor2;*/
#if defined(CONFIG_DRM_AMD_DC_DCN)
max_requested.FFE_PRESET =
link_training_setting->lane_settings[0].FFE_PRESET;
#endif
/* Determine what the maximum of the requested settings are*/ /* Determine what the maximum of the requested settings are*/
for (lane = 1; lane < link_training_setting->link_settings.lane_count; for (lane = 1; lane < link_training_setting->link_settings.lane_count;
...@@ -554,6 +798,13 @@ static void find_max_drive_settings( ...@@ -554,6 +798,13 @@ static void find_max_drive_settings(
link_training_setting->laneSettings[lane].postCursor2; link_training_setting->laneSettings[lane].postCursor2;
} }
*/ */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (link_training_setting->lane_settings[lane].FFE_PRESET.settings.level >
max_requested.FFE_PRESET.settings.level)
max_requested.FFE_PRESET.settings.level =
link_training_setting->
lane_settings[lane].FFE_PRESET.settings.level;
#endif
} }
/* make sure the requested settings are /* make sure the requested settings are
...@@ -567,6 +818,10 @@ static void find_max_drive_settings( ...@@ -567,6 +818,10 @@ static void find_max_drive_settings(
if (max_requested.postCursor2 > PostCursor2_MaxLevel) if (max_requested.postCursor2 > PostCursor2_MaxLevel)
max_requested.postCursor2 = PostCursor2_MaxLevel; max_requested.postCursor2 = PostCursor2_MaxLevel;
*/ */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
#endif
/* make sure the pre-emphasis matches the voltage swing*/ /* make sure the pre-emphasis matches the voltage swing*/
if (max_requested.PRE_EMPHASIS > if (max_requested.PRE_EMPHASIS >
...@@ -604,6 +859,10 @@ static void find_max_drive_settings( ...@@ -604,6 +859,10 @@ static void find_max_drive_settings(
/*max_lt_setting->laneSettings[lane].postCursor2 = /*max_lt_setting->laneSettings[lane].postCursor2 =
* max_requested.postCursor2; * max_requested.postCursor2;
*/ */
#if defined(CONFIG_DRM_AMD_DC_DCN)
max_lt_setting->lane_settings[lane].FFE_PRESET =
max_requested.FFE_PRESET;
#endif
} }
} }
...@@ -701,6 +960,13 @@ enum dc_status dp_get_lane_status_and_drive_settings( ...@@ -701,6 +960,13 @@ enum dc_status dp_get_lane_status_and_drive_settings(
(uint32_t)(link_training_setting->link_settings.lane_count); (uint32_t)(link_training_setting->link_settings.lane_count);
lane++) { lane++) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_128b_132b_ENCODING) {
request_settings.lane_settings[lane].FFE_PRESET.raw =
dpcd_lane_adjust[lane].tx_ffe.PRESET_VALUE;
} else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_8b_10b_ENCODING) {
request_settings.lane_settings[lane].VOLTAGE_SWING = request_settings.lane_settings[lane].VOLTAGE_SWING =
(enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits. (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
VOLTAGE_SWING_LANE); VOLTAGE_SWING_LANE);
...@@ -708,6 +974,15 @@ enum dc_status dp_get_lane_status_and_drive_settings( ...@@ -708,6 +974,15 @@ enum dc_status dp_get_lane_status_and_drive_settings(
(enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits. (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
PRE_EMPHASIS_LANE); PRE_EMPHASIS_LANE);
} }
#else
request_settings.lane_settings[lane].VOLTAGE_SWING =
(enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
VOLTAGE_SWING_LANE);
request_settings.lane_settings[lane].PRE_EMPHASIS =
(enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
PRE_EMPHASIS_LANE);
#endif
}
/*Note: for postcursor2, read adjusted /*Note: for postcursor2, read adjusted
* postcursor2 settings from*/ * postcursor2 settings from*/
...@@ -745,6 +1020,26 @@ enum dc_status dpcd_set_lane_settings( ...@@ -745,6 +1020,26 @@ enum dc_status dpcd_set_lane_settings(
(uint32_t)(link_training_setting-> (uint32_t)(link_training_setting->
link_settings.lane_count); link_settings.lane_count);
lane++) { lane++) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_128b_132b_ENCODING) {
dpcd_lane[lane].tx_ffe.PRESET_VALUE =
link_training_setting->lane_settings[lane].FFE_PRESET.settings.level;
} else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_8b_10b_ENCODING) {
dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
(uint8_t)(link_training_setting->lane_settings[lane].VOLTAGE_SWING);
dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
(uint8_t)(link_training_setting->lane_settings[lane].PRE_EMPHASIS);
dpcd_lane[lane].bits.MAX_SWING_REACHED =
(link_training_setting->lane_settings[lane].VOLTAGE_SWING ==
VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
(link_training_setting->lane_settings[lane].PRE_EMPHASIS ==
PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
}
#else
dpcd_lane[lane].bits.VOLTAGE_SWING_SET = dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
(uint8_t)(link_training_setting-> (uint8_t)(link_training_setting->
lane_settings[lane].VOLTAGE_SWING); lane_settings[lane].VOLTAGE_SWING);
...@@ -759,6 +1054,7 @@ enum dc_status dpcd_set_lane_settings( ...@@ -759,6 +1054,7 @@ enum dc_status dpcd_set_lane_settings(
(link_training_setting-> (link_training_setting->
lane_settings[lane].PRE_EMPHASIS == lane_settings[lane].PRE_EMPHASIS ==
PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
#endif
} }
status = core_link_write_dpcd(link, status = core_link_write_dpcd(link,
...@@ -786,6 +1082,18 @@ enum dc_status dpcd_set_lane_settings( ...@@ -786,6 +1082,18 @@ enum dc_status dpcd_set_lane_settings(
*/ */
if (is_repeater(link, offset)) { if (is_repeater(link, offset)) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_128b_132b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
" 0x%X TX_FFE_PRESET_VALUE = %x\n",
__func__,
offset,
lane0_set_address,
dpcd_lane[0].tx_ffe.PRESET_VALUE);
else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_8b_10b_ENCODING)
#endif
DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n" DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
" 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__, __func__,
...@@ -797,6 +1105,16 @@ enum dc_status dpcd_set_lane_settings( ...@@ -797,6 +1105,16 @@ enum dc_status dpcd_set_lane_settings(
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
} else { } else {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_128b_132b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
__func__,
lane0_set_address,
dpcd_lane[0].tx_ffe.PRESET_VALUE);
else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_8b_10b_ENCODING)
#endif
DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__, __func__,
lane0_set_address, lane0_set_address,
...@@ -932,6 +1250,14 @@ uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval ...@@ -932,6 +1250,14 @@ uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval
case 0x04: case 0x04:
aux_rd_interval_us = 16000; aux_rd_interval_us = 16000;
break; break;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case 0x05:
aux_rd_interval_us = 32000;
break;
case 0x06:
aux_rd_interval_us = 64000;
break;
#endif
default: default:
break; break;
} }
...@@ -972,8 +1298,13 @@ static enum link_training_result perform_channel_equalization_sequence( ...@@ -972,8 +1298,13 @@ static enum link_training_result perform_channel_equalization_sequence(
tr_pattern = lt_settings->pattern_for_eq; tr_pattern = lt_settings->pattern_for_eq;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_repeater(link, offset) && dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING)
tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
#else
if (is_repeater(link, offset)) if (is_repeater(link, offset))
tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4; tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
#endif
dp_set_hw_training_pattern(link, tr_pattern, offset); dp_set_hw_training_pattern(link, tr_pattern, offset);
...@@ -1125,9 +1456,28 @@ static enum link_training_result perform_clock_recovery_sequence( ...@@ -1125,9 +1456,28 @@ static enum link_training_result perform_clock_recovery_sequence(
return LINK_TRAINING_SUCCESS; return LINK_TRAINING_SUCCESS;
/* 6. max VS reached*/ /* 6. max VS reached*/
#if defined(CONFIG_DRM_AMD_DC_DCN)
if ((dp_get_link_encoding_format(&lt_settings->link_settings) ==
DP_8b_10b_ENCODING) &&
dp_is_max_vs_reached(lt_settings))
break;
#else
if (dp_is_max_vs_reached(lt_settings)) if (dp_is_max_vs_reached(lt_settings))
break; break;
#endif
#if defined(CONFIG_DRM_AMD_DC_DCN)
if ((dp_get_link_encoding_format(&lt_settings->link_settings) == DP_128b_132b_ENCODING) &&
lt_settings->lane_settings[0].FFE_PRESET.settings.level ==
req_settings.lane_settings[0].FFE_PRESET.settings.level)
retries_cr++;
else if ((dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING) &&
lt_settings->lane_settings[0].VOLTAGE_SWING ==
req_settings.lane_settings[0].VOLTAGE_SWING)
retries_cr++;
else
retries_cr = 0;
#else
/* 7. same lane settings*/ /* 7. same lane settings*/
/* Note: settings are the same for all lanes, /* Note: settings are the same for all lanes,
* so comparing first lane is sufficient*/ * so comparing first lane is sufficient*/
...@@ -1138,6 +1488,7 @@ static enum link_training_result perform_clock_recovery_sequence( ...@@ -1138,6 +1488,7 @@ static enum link_training_result perform_clock_recovery_sequence(
retries_cr++; retries_cr++;
else else
retries_cr = 0; retries_cr = 0;
#endif
/* 8. update VS/PE/PC2 in lt_settings*/ /* 8. update VS/PE/PC2 in lt_settings*/
dp_update_drive_settings(lt_settings, req_settings); dp_update_drive_settings(lt_settings, req_settings);
...@@ -1172,7 +1523,11 @@ static inline enum link_training_result dp_transition_to_video_idle( ...@@ -1172,7 +1523,11 @@ static inline enum link_training_result dp_transition_to_video_idle(
* TPS4 must be used instead of POST_LT_ADJ_REQ. * TPS4 must be used instead of POST_LT_ADJ_REQ.
*/ */
if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 || if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
#if defined(CONFIG_DRM_AMD_DC_DCN)
lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) {
#else
lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4) { lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4) {
#endif
/* delay 5ms after Main Link output idle pattern and then check /* delay 5ms after Main Link output idle pattern and then check
* DPCD 0202h. * DPCD 0202h.
*/ */
...@@ -1268,6 +1623,32 @@ static inline void decide_8b_10b_training_settings( ...@@ -1268,6 +1623,32 @@ static inline void decide_8b_10b_training_settings(
lt_settings->should_set_fec_ready = true; lt_settings->should_set_fec_ready = true;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
static inline void decide_128b_132b_training_settings(struct dc_link *link,
const struct dc_link_settings *link_settings,
struct link_training_settings *lt_settings)
{
memset(lt_settings, 0, sizeof(*lt_settings));
lt_settings->link_settings = *link_settings;
/* TODO: should decide link spread when populating link_settings */
lt_settings->link_settings.link_spread = link->dp_ss_off ? LINK_SPREAD_DISABLED :
LINK_SPREAD_05_DOWNSPREAD_30KHZ;
lt_settings->pattern_for_cr = decide_cr_training_pattern(link_settings);
lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_settings);
lt_settings->eq_pattern_time = 2500;
lt_settings->eq_wait_time_limit = 400000;
lt_settings->eq_loop_count_limit = 20;
lt_settings->pattern_for_cds = DP_128b_132b_TPS2_CDS;
lt_settings->cds_pattern_time = 2500;
lt_settings->cds_wait_time_limit = (dp_convert_to_count(
link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000;
lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ?
LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT;
}
#endif
void dp_decide_training_settings( void dp_decide_training_settings(
struct dc_link *link, struct dc_link *link,
const struct dc_link_settings *link_settings, const struct dc_link_settings *link_settings,
...@@ -1275,6 +1656,10 @@ void dp_decide_training_settings( ...@@ -1275,6 +1656,10 @@ void dp_decide_training_settings(
{ {
if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
decide_8b_10b_training_settings(link, link_settings, lt_settings); decide_8b_10b_training_settings(link, link_settings, lt_settings);
#if defined(CONFIG_DRM_AMD_DC_DCN)
else if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING)
decide_128b_132b_training_settings(link, link_settings, lt_settings);
#endif
} }
static void override_training_settings( static void override_training_settings(
...@@ -1303,6 +1688,11 @@ static void override_training_settings( ...@@ -1303,6 +1688,11 @@ static void override_training_settings(
lt_settings->pre_emphasis = overrides->pre_emphasis; lt_settings->pre_emphasis = overrides->pre_emphasis;
if (overrides->post_cursor2 != NULL) if (overrides->post_cursor2 != NULL)
lt_settings->post_cursor2 = overrides->post_cursor2; lt_settings->post_cursor2 = overrides->post_cursor2;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (overrides->ffe_preset != NULL)
lt_settings->ffe_preset = overrides->ffe_preset;
#endif
for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
lt_settings->lane_settings[lane].VOLTAGE_SWING = lt_settings->lane_settings[lane].VOLTAGE_SWING =
lt_settings->voltage_swing != NULL ? lt_settings->voltage_swing != NULL ?
...@@ -1489,6 +1879,17 @@ static void print_status_message( ...@@ -1489,6 +1879,17 @@ static void print_status_message(
case LINK_RATE_HIGH3: case LINK_RATE_HIGH3:
link_rate = "HBR3"; link_rate = "HBR3";
break; break;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case LINK_RATE_UHBR10:
link_rate = "UHBR10";
break;
case LINK_RATE_UHBR13_5:
link_rate = "UHBR13.5";
break;
case LINK_RATE_UHBR20:
link_rate = "UHBR20";
break;
#endif
default: default:
break; break;
} }
...@@ -1518,6 +1919,20 @@ static void print_status_message( ...@@ -1518,6 +1919,20 @@ static void print_status_message(
case LINK_TRAINING_LINK_LOSS: case LINK_TRAINING_LINK_LOSS:
lt_result = "Link loss"; lt_result = "Link loss";
break; break;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case DP_128b_132b_LT_FAILED:
lt_result = "LT_FAILED received";
break;
case DP_128b_132b_MAX_LOOP_COUNT_REACHED:
lt_result = "max loop count reached";
break;
case DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT:
lt_result = "channel EQ timeout";
break;
case DP_128b_132b_CDS_DONE_TIMEOUT:
lt_result = "CDS timeout";
break;
#endif
default: default:
break; break;
} }
...@@ -1537,6 +1952,9 @@ static void print_status_message( ...@@ -1537,6 +1952,9 @@ static void print_status_message(
} }
/* Connectivity log: link training */ /* Connectivity log: link training */
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* TODO - DP2.0 Log: add connectivity log for FFE PRESET */
#endif
CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s", CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",
link_rate, link_rate,
lt_settings->link_settings.lane_count, lt_settings->link_settings.lane_count,
...@@ -1619,9 +2037,23 @@ enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_train ...@@ -1619,9 +2037,23 @@ enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_train
static void dpcd_exit_training_mode(struct dc_link *link) static void dpcd_exit_training_mode(struct dc_link *link)
{ {
#if defined(CONFIG_DRM_AMD_DC_DCN)
uint8_t sink_status = 0;
uint8_t i;
#endif
/* clear training pattern set */ /* clear training pattern set */
dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE); dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* poll for intra-hop disable */
for (i = 0; i < 10; i++) {
if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
(sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
break;
udelay(1000);
}
#endif
} }
enum dc_status dpcd_configure_channel_coding(struct dc_link *link, enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
...@@ -1645,6 +2077,131 @@ enum dc_status dpcd_configure_channel_coding(struct dc_link *link, ...@@ -1645,6 +2077,131 @@ enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
return status; return status;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
static void dpcd_128b_132b_get_aux_rd_interval(struct dc_link *link,
uint32_t *interval_in_us)
{
union dp_128b_132b_training_aux_rd_interval dpcd_interval;
uint32_t interval_unit = 0;
dpcd_interval.raw = 0;
core_link_read_dpcd(link, DP_128b_132b_TRAINING_AUX_RD_INTERVAL,
&dpcd_interval.raw, sizeof(dpcd_interval.raw));
interval_unit = dpcd_interval.bits.UNIT ? 1 : 2; /* 0b = 2 ms, 1b = 1 ms */
/* (128b/132b_TRAINING_AUX_RD_INTERVAL value + 1) *
* INTERVAL_UNIT. The maximum is 256 ms
*/
*interval_in_us = (dpcd_interval.bits.VALUE + 1) * interval_unit * 1000;
}
static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
{
uint8_t loop_count = 0;
uint32_t aux_rd_interval = 0;
uint32_t wait_time = 0;
struct link_training_settings req_settings;
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
enum link_training_result status = LINK_TRAINING_SUCCESS;
/* Transmit 128b/132b_TPS1 over Main-Link and Set TRAINING_PATTERN_SET to 01h */
dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, DPRX);
dpcd_set_training_pattern(link, lt_settings->pattern_for_cr);
/* Adjust TX_FFE_PRESET_VALUE as requested */
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
&dpcd_lane_status_updated, &req_settings, DPRX);
dp_update_drive_settings(lt_settings, req_settings);
dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
dp_set_hw_lane_settings(link, lt_settings, DPRX);
dpcd_set_lane_settings(link, lt_settings, DPRX);
/* Transmit 128b/132b_TPS2 over Main-Link and Set TRAINING_PATTERN_SET to 02h */
dp_set_hw_training_pattern(link, lt_settings->pattern_for_eq, DPRX);
dpcd_set_training_pattern(link, lt_settings->pattern_for_eq);
/* poll for channel EQ done */
while (status == LINK_TRAINING_SUCCESS) {
loop_count++;
dp_wait_for_training_aux_rd_interval(link, aux_rd_interval);
wait_time += aux_rd_interval;
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
&dpcd_lane_status_updated, &req_settings, DPRX);
dp_update_drive_settings(lt_settings, req_settings);
dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
if (dp_is_ch_eq_done(lt_settings->link_settings.lane_count,
dpcd_lane_status)) {
/* pass */
break;
} else if (loop_count >= lt_settings->eq_loop_count_limit) {
status = DP_128b_132b_MAX_LOOP_COUNT_REACHED;
} else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
status = DP_128b_132b_LT_FAILED;
} else {
dp_set_hw_lane_settings(link, lt_settings, DPRX);
dpcd_set_lane_settings(link, lt_settings, DPRX);
}
}
/* poll for EQ interlane align done */
while (status == LINK_TRAINING_SUCCESS) {
if (dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b) {
/* pass */
break;
} else if (wait_time >= lt_settings->eq_wait_time_limit) {
status = DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT;
} else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
status = DP_128b_132b_LT_FAILED;
} else {
dp_wait_for_training_aux_rd_interval(link,
lt_settings->eq_pattern_time);
wait_time += lt_settings->eq_pattern_time;
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
&dpcd_lane_status_updated, &req_settings, DPRX);
}
}
return status;
}
static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
{
/* Assumption: assume hardware has transmitted eq pattern */
enum link_training_result status = LINK_TRAINING_SUCCESS;
struct link_training_settings req_settings;
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
uint32_t wait_time = 0;
/* initiate CDS done sequence */
dpcd_set_training_pattern(link, lt_settings->pattern_for_cds);
/* poll for CDS interlane align done and symbol lock */
while (status == LINK_TRAINING_SUCCESS) {
dp_wait_for_training_aux_rd_interval(link,
lt_settings->cds_pattern_time);
wait_time += lt_settings->cds_pattern_time;
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
&dpcd_lane_status_updated, &req_settings, DPRX);
if (dp_is_symbol_locked(lt_settings->link_settings.lane_count, dpcd_lane_status) &&
dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b) {
/* pass */
break;
} else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
status = DP_128b_132b_LT_FAILED;
} else if (wait_time >= lt_settings->cds_wait_time_limit) {
status = DP_128b_132b_CDS_DONE_TIMEOUT;
}
}
return status;
}
#endif
static enum link_training_result dp_perform_8b_10b_link_training( static enum link_training_result dp_perform_8b_10b_link_training(
struct dc_link *link, struct dc_link *link,
struct link_training_settings *lt_settings) struct link_training_settings *lt_settings)
...@@ -1701,6 +2258,35 @@ static enum link_training_result dp_perform_8b_10b_link_training( ...@@ -1701,6 +2258,35 @@ static enum link_training_result dp_perform_8b_10b_link_training(
return status; return status;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
static enum link_training_result dp_perform_128b_132b_link_training(
struct dc_link *link,
struct link_training_settings *lt_settings)
{
enum link_training_result result = LINK_TRAINING_SUCCESS;
/* TODO - DP2.0 Link: remove legacy_dp2_lt logic */
if (link->dc->debug.legacy_dp2_lt) {
struct link_training_settings legacy_settings;
decide_8b_10b_training_settings(link,
&lt_settings->link_settings,
&legacy_settings);
return dp_perform_8b_10b_link_training(link, &legacy_settings);
}
dpcd_set_link_settings(link, lt_settings);
if (result == LINK_TRAINING_SUCCESS)
result = dp_perform_128b_132b_channel_eq_done_sequence(link, lt_settings);
if (result == LINK_TRAINING_SUCCESS)
result = dp_perform_128b_132b_cds_done_sequence(link, lt_settings);
return result;
}
#endif
enum link_training_result dc_link_dp_perform_link_training( enum link_training_result dc_link_dp_perform_link_training(
struct dc_link *link, struct dc_link *link,
const struct dc_link_settings *link_settings, const struct dc_link_settings *link_settings,
...@@ -1735,6 +2321,10 @@ enum link_training_result dc_link_dp_perform_link_training( ...@@ -1735,6 +2321,10 @@ enum link_training_result dc_link_dp_perform_link_training(
*/ */
if (encoding == DP_8b_10b_ENCODING) if (encoding == DP_8b_10b_ENCODING)
status = dp_perform_8b_10b_link_training(link, &lt_settings); status = dp_perform_8b_10b_link_training(link, &lt_settings);
#if defined(CONFIG_DRM_AMD_DC_DCN)
else if (encoding == DP_128b_132b_ENCODING)
status = dp_perform_128b_132b_link_training(link, &lt_settings);
#endif
else else
ASSERT(0); ASSERT(0);
...@@ -1780,6 +2370,9 @@ bool perform_link_training_with_retries( ...@@ -1780,6 +2370,9 @@ bool perform_link_training_with_retries(
/* We need to do this before the link training to ensure the idle pattern in SST /* 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 * mode will be sent right after the link training
*/ */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&current_setting) == DP_8b_10b_ENCODING)
#endif
link_enc->funcs->connect_dig_be_to_fe(link_enc, link_enc->funcs->connect_dig_be_to_fe(link_enc,
pipe_ctx->stream_res.stream_enc->id, true); pipe_ctx->stream_res.stream_enc->id, true);
...@@ -1950,8 +2543,14 @@ enum link_training_result dc_link_dp_sync_lt_attempt( ...@@ -1950,8 +2543,14 @@ enum link_training_result dc_link_dp_sync_lt_attempt(
dp_cs_id, link_settings); dp_cs_id, link_settings);
/* Set FEC enable */ /* Set FEC enable */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
#endif
fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable; fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
dp_set_fec_ready(link, fec_enable); dp_set_fec_ready(link, fec_enable);
#if defined(CONFIG_DRM_AMD_DC_DCN)
}
#endif
if (lt_overrides->alternate_scrambler_reset) { if (lt_overrides->alternate_scrambler_reset) {
if (*lt_overrides->alternate_scrambler_reset) if (*lt_overrides->alternate_scrambler_reset)
...@@ -1993,7 +2592,13 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down) ...@@ -1993,7 +2592,13 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
* Still shouldn't turn off dp_receiver (DPCD:600h) * Still shouldn't turn off dp_receiver (DPCD:600h)
*/ */
if (link_down == true) { if (link_down == true) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dc_link_settings link_settings = link->cur_link_settings;
#endif
dp_disable_link_phy(link, link->connector_signal); dp_disable_link_phy(link, link->connector_signal);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING)
#endif
dp_set_fec_ready(link, false); dp_set_fec_ready(link, false);
} }
...@@ -2001,6 +2606,22 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down) ...@@ -2001,6 +2606,22 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
return true; return true;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
{
enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20)
lttpr_max_link_rate = LINK_RATE_UHBR20;
else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5)
lttpr_max_link_rate = LINK_RATE_UHBR13_5;
else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR10)
lttpr_max_link_rate = LINK_RATE_UHBR10;
return lttpr_max_link_rate;
}
#endif
bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
{ {
if (!max_link_enc_cap) { if (!max_link_enc_cap) {
...@@ -2022,9 +2643,17 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_ ...@@ -2022,9 +2643,17 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_
static struct dc_link_settings get_max_link_cap(struct dc_link *link) static struct dc_link_settings get_max_link_cap(struct dc_link *link)
{ {
struct dc_link_settings max_link_cap = {0}; struct dc_link_settings max_link_cap = {0};
#if defined(CONFIG_DRM_AMD_DC_DCN)
enum dc_link_rate lttpr_max_link_rate;
#endif
/* get max link encoder capability */ /* get max link encoder capability */
link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap); link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (max_link_cap.link_rate >= LINK_RATE_UHBR10 &&
!link->hpo_dp_link_enc)
max_link_cap.link_rate = LINK_RATE_HIGH3;
#endif
/* Lower link settings based on sink's link cap */ /* Lower link settings based on sink's link cap */
if (link->reported_link_cap.lane_count < max_link_cap.lane_count) if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
...@@ -2045,8 +2674,15 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) ...@@ -2045,8 +2674,15 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link)
if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
#if defined(CONFIG_DRM_AMD_DC_DCN)
lttpr_max_link_rate = get_lttpr_max_link_rate(link);
if (lttpr_max_link_rate < max_link_cap.link_rate)
max_link_cap.link_rate = lttpr_max_link_rate;
#else
if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate) if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate)
max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate; max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
#endif
DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n", DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
__func__, __func__,
...@@ -2205,6 +2841,10 @@ bool dp_verify_link_cap( ...@@ -2205,6 +2841,10 @@ bool dp_verify_link_cap(
core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant)); core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING)
reset_dp_hpo_stream_encoders_for_link(link);
#endif
/* TODO implement override and monitor patch later */ /* TODO implement override and monitor patch later */
/* try to train the link from high to low to /* try to train the link from high to low to
...@@ -2360,7 +3000,17 @@ static struct dc_link_settings get_common_supported_link_settings( ...@@ -2360,7 +3000,17 @@ static struct dc_link_settings get_common_supported_link_settings(
* We map it to the maximum supported link rate that * We map it to the maximum supported link rate that
* is smaller than MAX_LINK_BW in this case. * is smaller than MAX_LINK_BW in this case.
*/ */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (link_settings.link_rate > LINK_RATE_UHBR20) {
link_settings.link_rate = LINK_RATE_UHBR20;
} else if (link_settings.link_rate < LINK_RATE_UHBR20 &&
link_settings.link_rate > LINK_RATE_UHBR13_5) {
link_settings.link_rate = LINK_RATE_UHBR13_5;
} else if (link_settings.link_rate < LINK_RATE_UHBR10 &&
link_settings.link_rate > LINK_RATE_HIGH3) {
#else
if (link_settings.link_rate > LINK_RATE_HIGH3) { if (link_settings.link_rate > LINK_RATE_HIGH3) {
#endif
link_settings.link_rate = LINK_RATE_HIGH3; link_settings.link_rate = LINK_RATE_HIGH3;
} else if (link_settings.link_rate < LINK_RATE_HIGH3 } else if (link_settings.link_rate < LINK_RATE_HIGH3
&& link_settings.link_rate > LINK_RATE_HIGH2) { && link_settings.link_rate > LINK_RATE_HIGH2) {
...@@ -2405,6 +3055,14 @@ static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) ...@@ -2405,6 +3055,14 @@ static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
{ {
switch (link_rate) { switch (link_rate) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
case LINK_RATE_UHBR20:
return LINK_RATE_UHBR13_5;
case LINK_RATE_UHBR13_5:
return LINK_RATE_UHBR10;
case LINK_RATE_UHBR10:
return LINK_RATE_HIGH3;
#endif
case LINK_RATE_HIGH3: case LINK_RATE_HIGH3:
return LINK_RATE_HIGH2; return LINK_RATE_HIGH2;
case LINK_RATE_HIGH2: case LINK_RATE_HIGH2:
...@@ -2439,11 +3097,55 @@ static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) ...@@ -2439,11 +3097,55 @@ static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate)
return LINK_RATE_HIGH2; return LINK_RATE_HIGH2;
case LINK_RATE_HIGH2: case LINK_RATE_HIGH2:
return LINK_RATE_HIGH3; return LINK_RATE_HIGH3;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case LINK_RATE_HIGH3:
return LINK_RATE_UHBR10;
case LINK_RATE_UHBR10:
return LINK_RATE_UHBR13_5;
case LINK_RATE_UHBR13_5:
return LINK_RATE_UHBR20;
#endif
default: default:
return LINK_RATE_UNKNOWN; return LINK_RATE_UNKNOWN;
} }
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
static bool decide_fallback_link_setting_max_bw_policy(
const struct dc_link_settings *max,
struct dc_link_settings *cur)
{
uint8_t cur_idx = 0, next_idx;
bool found = false;
while (cur_idx < ARRAY_SIZE(dp_lt_fallbacks))
/* find current index */
if (dp_lt_fallbacks[cur_idx].lane_count == cur->lane_count &&
dp_lt_fallbacks[cur_idx].link_rate == cur->link_rate)
break;
else
cur_idx++;
next_idx = cur_idx + 1;
while (next_idx < ARRAY_SIZE(dp_lt_fallbacks))
/* find next index */
if (dp_lt_fallbacks[next_idx].lane_count <= max->lane_count &&
dp_lt_fallbacks[next_idx].link_rate <= max->link_rate)
break;
else
next_idx++;
if (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) {
cur->lane_count = dp_lt_fallbacks[next_idx].lane_count;
cur->link_rate = dp_lt_fallbacks[next_idx].link_rate;
found = true;
}
return found;
}
#endif
/* /*
* function: set link rate and lane count fallback based * function: set link rate and lane count fallback based
* on current link setting and last link training result * on current link setting and last link training result
...@@ -2459,6 +3161,11 @@ static bool decide_fallback_link_setting( ...@@ -2459,6 +3161,11 @@ static bool decide_fallback_link_setting(
{ {
if (!current_link_setting) if (!current_link_setting)
return false; return false;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&initial_link_settings) == DP_128b_132b_ENCODING)
return decide_fallback_link_setting_max_bw_policy(&initial_link_settings,
current_link_setting);
#endif
switch (training_result) { switch (training_result) {
case LINK_TRAINING_CR_FAIL_LANE0: case LINK_TRAINING_CR_FAIL_LANE0:
...@@ -2831,9 +3538,15 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) ...@@ -2831,9 +3538,15 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
union phy_test_pattern dpcd_test_pattern; union phy_test_pattern dpcd_test_pattern;
union lane_adjust dpcd_lane_adjustment[2]; union lane_adjust dpcd_lane_adjustment[2];
unsigned char dpcd_post_cursor_2_adjustment = 0; unsigned char dpcd_post_cursor_2_adjustment = 0;
#if defined(CONFIG_DRM_AMD_DC_DCN)
unsigned char test_pattern_buffer[
(DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -
DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0};
#else
unsigned char test_pattern_buffer[ unsigned char test_pattern_buffer[
(DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0};
#endif
unsigned int test_pattern_size = 0; unsigned int test_pattern_size = 0;
enum dp_test_pattern test_pattern; enum dp_test_pattern test_pattern;
struct dc_link_training_settings link_settings; struct dc_link_training_settings link_settings;
...@@ -2899,6 +3612,35 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) ...@@ -2899,6 +3612,35 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
case PHY_TEST_PATTERN_CP2520_3: case PHY_TEST_PATTERN_CP2520_3:
test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
break; break;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case PHY_TEST_PATTERN_128b_132b_TPS1:
test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
break;
case PHY_TEST_PATTERN_128b_132b_TPS2:
test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
break;
case PHY_TEST_PATTERN_PRBS9:
test_pattern = DP_TEST_PATTERN_PRBS9;
break;
case PHY_TEST_PATTERN_PRBS11:
test_pattern = DP_TEST_PATTERN_PRBS11;
break;
case PHY_TEST_PATTERN_PRBS15:
test_pattern = DP_TEST_PATTERN_PRBS15;
break;
case PHY_TEST_PATTERN_PRBS23:
test_pattern = DP_TEST_PATTERN_PRBS23;
break;
case PHY_TEST_PATTERN_PRBS31:
test_pattern = DP_TEST_PATTERN_PRBS31;
break;
case PHY_TEST_PATTERN_264BIT_CUSTOM:
test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
break;
case PHY_TEST_PATTERN_SQUARE_PULSE:
test_pattern = DP_TEST_PATTERN_SQUARE_PULSE;
break;
#endif
default: default:
test_pattern = DP_TEST_PATTERN_VIDEO_MODE; test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
break; break;
...@@ -2914,6 +3656,27 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) ...@@ -2914,6 +3656,27 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
test_pattern_size); test_pattern_size);
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE) {
test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
core_link_read_dpcd(
link,
DP_PHY_SQUARE_PATTERN,
test_pattern_buffer,
test_pattern_size);
}
if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256-
DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1;
core_link_read_dpcd(
link,
DP_TEST_264BIT_CUSTOM_PATTERN_7_0,
test_pattern_buffer,
test_pattern_size);
}
#endif
/* prepare link training settings */ /* prepare link training settings */
link_settings.link = link->cur_link_settings; link_settings.link = link->cur_link_settings;
...@@ -2922,6 +3685,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) ...@@ -2922,6 +3685,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
lane++) { lane++) {
dpcd_lane_adjust.raw = dpcd_lane_adjust.raw =
get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link->cur_link_settings) ==
DP_128b_132b_ENCODING) {
link_settings.lane_settings[lane].FFE_PRESET.raw =
dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
} else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
DP_8b_10b_ENCODING) {
link_settings.lane_settings[lane].VOLTAGE_SWING = link_settings.lane_settings[lane].VOLTAGE_SWING =
(enum dc_voltage_swing) (enum dc_voltage_swing)
(dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE); (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
...@@ -2932,6 +3702,18 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) ...@@ -2932,6 +3702,18 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
(enum dc_post_cursor2) (enum dc_post_cursor2)
((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
} }
#else
link_settings.lane_settings[lane].VOLTAGE_SWING =
(enum dc_voltage_swing)
(dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
link_settings.lane_settings[lane].PRE_EMPHASIS =
(enum dc_pre_emphasis)
(dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
link_settings.lane_settings[lane].POST_CURSOR2 =
(enum dc_post_cursor2)
((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
#endif
}
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
link_training_settings.lane_settings[i] = link_training_settings.lane_settings[i] =
...@@ -3535,6 +4317,43 @@ static void get_active_converter_info( ...@@ -3535,6 +4317,43 @@ static void get_active_converter_info(
dp_hw_fw_revision.ieee_fw_rev, dp_hw_fw_revision.ieee_fw_rev,
sizeof(dp_hw_fw_revision.ieee_fw_rev)); sizeof(dp_hw_fw_revision.ieee_fw_rev));
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
union dp_dfp_cap_ext dfp_cap_ext;
memset(&dfp_cap_ext, '\0', sizeof (dfp_cap_ext));
core_link_read_dpcd(
link,
DP_DFP_CAPABILITY_EXTENSION_SUPPORT,
dfp_cap_ext.raw,
sizeof(dfp_cap_ext.raw));
link->dpcd_caps.dongle_caps.dfp_cap_ext.supported = dfp_cap_ext.fields.supported;
link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps =
dfp_cap_ext.fields.max_pixel_rate_in_mps[0] +
(dfp_cap_ext.fields.max_pixel_rate_in_mps[1] << 8);
link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width =
dfp_cap_ext.fields.max_video_h_active_width[0] +
(dfp_cap_ext.fields.max_video_h_active_width[1] << 8);
link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height =
dfp_cap_ext.fields.max_video_v_active_height[0] +
(dfp_cap_ext.fields.max_video_v_active_height[1] << 8);
link->dpcd_caps.dongle_caps.dfp_cap_ext.encoding_format_caps =
dfp_cap_ext.fields.encoding_format_caps;
link->dpcd_caps.dongle_caps.dfp_cap_ext.rgb_color_depth_caps =
dfp_cap_ext.fields.rgb_color_depth_caps;
link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr444_color_depth_caps =
dfp_cap_ext.fields.ycbcr444_color_depth_caps;
link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr422_color_depth_caps =
dfp_cap_ext.fields.ycbcr422_color_depth_caps;
link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr420_color_depth_caps =
dfp_cap_ext.fields.ycbcr420_color_depth_caps;
DC_LOG_DP2("DFP capability extension is read at link %d", link->link_index);
DC_LOG_DP2("\tdfp_cap_ext.supported = %s", link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true" : "false");
DC_LOG_DP2("\tdfp_cap_ext.max_pixel_rate_in_mps = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps);
DC_LOG_DP2("\tdfp_cap_ext.max_video_h_active_width = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width);
DC_LOG_DP2("\tdfp_cap_ext.max_video_v_active_height = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height);
}
#endif
} }
static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data, static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
...@@ -3594,7 +4413,12 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) ...@@ -3594,7 +4413,12 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
bool dp_retrieve_lttpr_cap(struct dc_link *link) bool dp_retrieve_lttpr_cap(struct dc_link *link)
{ {
#if defined(CONFIG_DRM_AMD_DC_DCN)
uint8_t lttpr_dpcd_data[8];
bool allow_lttpr_non_transparent_mode = 0;
#else
uint8_t lttpr_dpcd_data[6]; uint8_t lttpr_dpcd_data[6];
#endif
bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable; bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
enum dc_status status = DC_ERROR_UNEXPECTED; enum dc_status status = DC_ERROR_UNEXPECTED;
...@@ -3602,6 +4426,16 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) ...@@ -3602,6 +4426,16 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data)); memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
#if defined(CONFIG_DRM_AMD_DC_DCN)
if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 &&
link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) {
allow_lttpr_non_transparent_mode = 1;
} else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
!link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
allow_lttpr_non_transparent_mode = 1;
}
#endif
/* /*
* Logic to determine LTTPR mode * Logic to determine LTTPR mode
*/ */
...@@ -3609,13 +4443,21 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) ...@@ -3609,13 +4443,21 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
if (vbios_lttpr_enable && vbios_lttpr_interop) if (vbios_lttpr_enable && vbios_lttpr_interop)
link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
else if (!vbios_lttpr_enable && vbios_lttpr_interop) { else if (!vbios_lttpr_enable && vbios_lttpr_interop) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (allow_lttpr_non_transparent_mode)
#else
if (link->dc->config.allow_lttpr_non_transparent_mode) if (link->dc->config.allow_lttpr_non_transparent_mode)
#endif
link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
else else
link->lttpr_mode = LTTPR_MODE_TRANSPARENT; link->lttpr_mode = LTTPR_MODE_TRANSPARENT;
} else if (!vbios_lttpr_enable && !vbios_lttpr_interop) { } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support)
#else
if (!link->dc->config.allow_lttpr_non_transparent_mode if (!link->dc->config.allow_lttpr_non_transparent_mode
|| !link->dc->caps.extended_aux_timeout_support) || !link->dc->caps.extended_aux_timeout_support)
#endif
link->lttpr_mode = LTTPR_MODE_NON_LTTPR; link->lttpr_mode = LTTPR_MODE_NON_LTTPR;
else else
link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT;
...@@ -3659,6 +4501,16 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) ...@@ -3659,6 +4501,16 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
#if defined(CONFIG_DRM_AMD_DC_DCN)
link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw =
lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw =
lttpr_dpcd_data[DP_PHY_REPEATER_128b_132b_RATES -
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
#endif
/* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 &&
link->dpcd_caps.lttpr_caps.max_lane_count > 0 && link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
...@@ -3909,16 +4761,82 @@ static bool retrieve_link_cap(struct dc_link *link) ...@@ -3909,16 +4761,82 @@ static bool retrieve_link_cap(struct dc_link *link)
DP_DSC_SUPPORT, DP_DSC_SUPPORT,
link->dpcd_caps.dsc_caps.dsc_basic_caps.raw, link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw)); sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
status = core_link_read_dpcd(
link,
DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
DC_LOG_DSC("DSC branch decoder capability is read at link %d", link->link_index);
DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x",
link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_0);
DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x",
link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_1);
DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x",
link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH);
}
#else
status = core_link_read_dpcd( status = core_link_read_dpcd(
link, link,
DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw)); sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
#endif
} }
if (!dpcd_read_sink_ext_caps(link)) if (!dpcd_read_sink_ext_caps(link))
link->dpcd_sink_ext_caps.raw = 0; link->dpcd_sink_ext_caps.raw = 0;
#if defined(CONFIG_DRM_AMD_DC_DCN)
link->dpcd_caps.channel_coding_cap.raw = dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_CAP - DP_DPCD_REV];
if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
DC_LOG_DP2("128b/132b encoding is supported at link %d", link->link_index);
core_link_read_dpcd(link,
DP_128b_132b_SUPPORTED_LINK_RATES,
&link->dpcd_caps.dp_128b_132b_supported_link_rates.raw,
sizeof(link->dpcd_caps.dp_128b_132b_supported_link_rates.raw));
if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR20)
link->reported_link_cap.link_rate = LINK_RATE_UHBR20;
else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5)
link->reported_link_cap.link_rate = LINK_RATE_UHBR13_5;
else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR10)
link->reported_link_cap.link_rate = LINK_RATE_UHBR10;
else
dm_error("%s: Invalid RX 128b_132b_supported_link_rates\n", __func__);
DC_LOG_DP2("128b/132b supported link rates is read at link %d", link->link_index);
DC_LOG_DP2("\tmax 128b/132b link rate support is %d.%d GHz",
link->reported_link_cap.link_rate / 100,
link->reported_link_cap.link_rate % 100);
core_link_read_dpcd(link,
DP_SINK_VIDEO_FALLBACK_FORMATS,
&link->dpcd_caps.fallback_formats.raw,
sizeof(link->dpcd_caps.fallback_formats.raw));
DC_LOG_DP2("sink video fallback format is read at link %d", link->link_index);
if (link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support)
DC_LOG_DP2("\t1920x1080@60Hz 24bpp fallback format supported");
if (link->dpcd_caps.fallback_formats.bits.dp_1280x720_60Hz_24bpp_support)
DC_LOG_DP2("\t1280x720@60Hz 24bpp fallback format supported");
if (link->dpcd_caps.fallback_formats.bits.dp_1024x768_60Hz_24bpp_support)
DC_LOG_DP2("\t1024x768@60Hz 24bpp fallback format supported");
if (link->dpcd_caps.fallback_formats.raw == 0) {
DC_LOG_DP2("\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported");
link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support = 1;
}
core_link_read_dpcd(link,
DP_FEC_CAPABILITY_1,
&link->dpcd_caps.fec_cap1.raw,
sizeof(link->dpcd_caps.fec_cap1.raw));
DC_LOG_DP2("FEC CAPABILITY 1 is read at link %d", link->link_index);
if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE)
DC_LOG_DP2("\tFEC aggregated error counters are supported");
}
#endif
/* Connectivity log: detection */ /* Connectivity log: detection */
CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
...@@ -4389,6 +5307,35 @@ bool dc_link_dp_set_test_pattern( ...@@ -4389,6 +5307,35 @@ bool dc_link_dp_set_test_pattern(
case DP_TEST_PATTERN_CP2520_3: case DP_TEST_PATTERN_CP2520_3:
pattern = PHY_TEST_PATTERN_CP2520_3; pattern = PHY_TEST_PATTERN_CP2520_3;
break; break;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case DP_TEST_PATTERN_128b_132b_TPS1:
pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
break;
case DP_TEST_PATTERN_128b_132b_TPS2:
pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
break;
case DP_TEST_PATTERN_PRBS9:
pattern = PHY_TEST_PATTERN_PRBS9;
break;
case DP_TEST_PATTERN_PRBS11:
pattern = PHY_TEST_PATTERN_PRBS11;
break;
case DP_TEST_PATTERN_PRBS15:
pattern = PHY_TEST_PATTERN_PRBS15;
break;
case DP_TEST_PATTERN_PRBS23:
pattern = PHY_TEST_PATTERN_PRBS23;
break;
case DP_TEST_PATTERN_PRBS31:
pattern = PHY_TEST_PATTERN_PRBS31;
break;
case DP_TEST_PATTERN_264BIT_CUSTOM:
pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
break;
case DP_TEST_PATTERN_SQUARE_PULSE:
pattern = PHY_TEST_PATTERN_SQUARE_PULSE;
break;
#endif
default: default:
return false; return false;
} }
...@@ -4964,6 +5911,208 @@ enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings ...@@ -4964,6 +5911,208 @@ enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings
if ((link_settings->link_rate >= LINK_RATE_LOW) && if ((link_settings->link_rate >= LINK_RATE_LOW) &&
(link_settings->link_rate <= LINK_RATE_HIGH3)) (link_settings->link_rate <= LINK_RATE_HIGH3))
return DP_8b_10b_ENCODING; return DP_8b_10b_ENCODING;
#if defined(CONFIG_DRM_AMD_DC_DCN)
else if ((link_settings->link_rate >= LINK_RATE_UHBR10) &&
(link_settings->link_rate <= LINK_RATE_UHBR20))
return DP_128b_132b_ENCODING;
#endif
return DP_UNKNOWN_ENCODING; return DP_UNKNOWN_ENCODING;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)
static void get_lane_status(
struct dc_link *link,
uint32_t lane_count,
union lane_status *status,
union lane_align_status_updated *status_updated)
{
unsigned int lane;
uint8_t dpcd_buf[3] = {0};
if (status == NULL || status_updated == NULL) {
return;
}
core_link_read_dpcd(
link,
DP_LANE0_1_STATUS,
dpcd_buf,
sizeof(dpcd_buf));
for (lane = 0; lane < lane_count; lane++) {
status[lane].raw = get_nibble_at_index(&dpcd_buf[0], lane);
}
status_updated->raw = dpcd_buf[2];
}
bool dpcd_write_128b_132b_sst_payload_allocation_table(
const struct dc_stream_state *stream,
struct dc_link *link,
struct link_mst_stream_allocation_table *proposed_table,
bool allocate)
{
const uint8_t vc_id = 1; /// VC ID always 1 for SST
const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST
bool result = false;
uint8_t req_slot_count = 0;
struct fixed31_32 avg_time_slots_per_mtp = { 0 };
union payload_table_update_status update_status = { 0 };
const uint32_t max_retries = 30;
uint32_t retries = 0;
if (allocate) {
avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
} else {
/// Leave req_slot_count = 0 if allocate is false.
}
/// Write DPCD 2C0 = 1 to start updating
update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;
core_link_write_dpcd(
link,
DP_PAYLOAD_TABLE_UPDATE_STATUS,
&update_status.raw,
1);
/// Program the changes in DPCD 1C0 - 1C2
ASSERT(vc_id == 1);
core_link_write_dpcd(
link,
DP_PAYLOAD_ALLOCATE_SET,
&vc_id,
1);
ASSERT(start_time_slot == 0);
core_link_write_dpcd(
link,
DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,
&start_time_slot,
1);
ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT); /// Validation should filter out modes that exceed link BW
core_link_write_dpcd(
link,
DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,
&req_slot_count,
1);
/// Poll till DPCD 2C0 read 1
/// Try for at least 150ms (30 retries, with 5ms delay after each attempt)
while (retries < max_retries) {
if (core_link_read_dpcd(
link,
DP_PAYLOAD_TABLE_UPDATE_STATUS,
&update_status.raw,
1) == DC_OK) {
if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {
DC_LOG_DP2("SST Update Payload: downstream payload table updated.");
result = true;
break;
}
} else {
union dpcd_rev dpcdRev;
if (core_link_read_dpcd(
link,
DP_DPCD_REV,
&dpcdRev.raw,
1) != DC_OK) {
DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "
"of sink while polling payload table "
"updated status bit.");
break;
}
}
retries++;
udelay(5000);
}
if (!result && retries == max_retries) {
DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "
"continue on. Something is wrong with the branch.");
// TODO - DP2.0 Payload: Read and log the payload table from downstream branch
}
proposed_table->stream_count = 1; /// Always 1 stream for SST
proposed_table->stream_allocations[0].slot_count = req_slot_count;
proposed_table->stream_allocations[0].vcp_id = vc_id;
return result;
}
bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link)
{
/*
* wait for ACT handled
*/
int i;
const int act_retries = 30;
enum act_return_status result = ACT_FAILED;
union payload_table_update_status update_status = {0};
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
union lane_align_status_updated lane_status_updated;
for (i = 0; i < act_retries; i++) {
get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
!dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||
!dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||
!dp_is_interlane_aligned(lane_status_updated)) {
DC_LOG_ERROR("SST Update Payload: Link loss occurred while "
"polling for ACT handled.");
result = ACT_LINK_LOST;
break;
}
core_link_read_dpcd(
link,
DP_PAYLOAD_TABLE_UPDATE_STATUS,
&update_status.raw,
1);
if (update_status.bits.ACT_HANDLED == 1) {
DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");
result = ACT_SUCCESS;
break;
}
udelay(5000);
}
if (result == ACT_FAILED) {
DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "
"continue on. Something is wrong with the branch.");
}
return (result == ACT_SUCCESS);
}
struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
const struct dc_stream_state *stream,
const struct dc_link *link)
{
struct fixed31_32 link_bw_effective =
dc_fixpt_from_int(
dc_link_bandwidth_kbps(link, &link->cur_link_settings));
struct fixed31_32 timeslot_bw_effective =
dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);
struct fixed31_32 timing_bw =
dc_fixpt_from_int(
dc_bandwidth_in_kbps_from_timing(&stream->timing));
struct fixed31_32 avg_time_slots_per_mtp =
dc_fixpt_div(timing_bw, timeslot_bw_effective);
return avg_time_slots_per_mtp;
}
bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx)
{
return (pipe_ctx->stream_res.hpo_dp_stream_enc &&
pipe_ctx->stream->link->hpo_dp_link_enc &&
dc_is_dp_signal(pipe_ctx->stream->signal));
}
#endif
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "link_enc_cfg.h" #include "link_enc_cfg.h"
#include "clk_mgr.h" #include "clk_mgr.h"
#include "inc/link_dpcd.h" #include "inc/link_dpcd.h"
#include "dccg.h"
static uint8_t convert_to_count(uint8_t lttpr_repeater_count) static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
{ {
...@@ -111,12 +112,24 @@ void dp_enable_link_phy( ...@@ -111,12 +112,24 @@ void dp_enable_link_phy(
link->cur_link_settings = *link_settings; link->cur_link_settings = *link_settings;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
/* TODO - DP2.0 HW: notify link rate change here */
} else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
if (dc->clk_mgr->funcs->notify_link_rate_change) if (dc->clk_mgr->funcs->notify_link_rate_change)
dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
}
#else
if (dc->clk_mgr->funcs->notify_link_rate_change)
dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
#endif
if (dmcu != NULL && dmcu->funcs->lock_phy) if (dmcu != NULL && dmcu->funcs->lock_phy)
dmcu->funcs->lock_phy(dmcu); dmcu->funcs->lock_phy(dmcu);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
enable_dp_hpo_output(link, link_settings);
} else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
if (dc_is_dp_sst_signal(signal)) { if (dc_is_dp_sst_signal(signal)) {
link_enc->funcs->enable_dp_output( link_enc->funcs->enable_dp_output(
link_enc, link_enc,
...@@ -128,7 +141,20 @@ void dp_enable_link_phy( ...@@ -128,7 +141,20 @@ void dp_enable_link_phy(
link_settings, link_settings,
clock_source); clock_source);
} }
}
#else
if (dc_is_dp_sst_signal(signal)) {
link_enc->funcs->enable_dp_output(
link_enc,
link_settings,
clock_source);
} else {
link_enc->funcs->enable_dp_mst_output(
link_enc,
link_settings,
clock_source);
}
#endif
if (dmcu != NULL && dmcu->funcs->unlock_phy) if (dmcu != NULL && dmcu->funcs->unlock_phy)
dmcu->funcs->unlock_phy(dmcu); dmcu->funcs->unlock_phy(dmcu);
...@@ -206,6 +232,9 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) ...@@ -206,6 +232,9 @@ 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;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct hpo_dp_link_encoder *hpo_link_enc = link->hpo_dp_link_enc;
#endif
struct link_encoder *link_enc; struct link_encoder *link_enc;
/* Link should always be assigned encoder when en-/disabling. */ /* Link should always be assigned encoder when en-/disabling. */
...@@ -221,14 +250,28 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) ...@@ -221,14 +250,28 @@ 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);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING)
disable_dp_hpo_output(link, signal);
else
link_enc->funcs->disable_output(link_enc, signal); link_enc->funcs->disable_output(link_enc, signal);
#else
link_enc->funcs->disable_output(link_enc, signal);
#endif
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);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING &&
hpo_link_enc)
disable_dp_hpo_output(link, signal);
else
link_enc->funcs->disable_output(link_enc, signal); link_enc->funcs->disable_output(link_enc, signal);
#else
link_enc->funcs->disable_output(link_enc, signal);
#endif
if (dmcu != NULL && dmcu->funcs->unlock_phy) if (dmcu != NULL && dmcu->funcs->unlock_phy)
dmcu->funcs->unlock_phy(dmcu); dmcu->funcs->unlock_phy(dmcu);
} }
...@@ -273,6 +316,14 @@ bool dp_set_hw_training_pattern( ...@@ -273,6 +316,14 @@ bool dp_set_hw_training_pattern(
case DP_TRAINING_PATTERN_SEQUENCE_4: case DP_TRAINING_PATTERN_SEQUENCE_4:
test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
break; break;
#if defined(CONFIG_DRM_AMD_DC_DCN)
case DP_128b_132b_TPS1:
test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE;
break;
case DP_128b_132b_TPS2:
test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE;
break;
#endif
default: default:
break; break;
} }
...@@ -282,6 +333,10 @@ bool dp_set_hw_training_pattern( ...@@ -282,6 +333,10 @@ bool dp_set_hw_training_pattern(
return true; return true;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
#define DC_LOGGER \
link->ctx->logger
#endif
void dp_set_hw_lane_settings( void dp_set_hw_lane_settings(
struct dc_link *link, struct dc_link *link,
const struct link_training_settings *link_settings, const struct link_training_settings *link_settings,
...@@ -293,7 +348,20 @@ void dp_set_hw_lane_settings( ...@@ -293,7 +348,20 @@ void dp_set_hw_lane_settings(
return; return;
/* call Encoder to set lane settings */ /* call Encoder to set lane settings */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dp_get_link_encoding_format(&link_settings->link_settings) ==
DP_128b_132b_ENCODING) {
link->hpo_dp_link_enc->funcs->set_ffe(
link->hpo_dp_link_enc,
&link_settings->link_settings,
link_settings->lane_settings[0].FFE_PRESET.raw);
} else if (dp_get_link_encoding_format(&link_settings->link_settings)
== DP_8b_10b_ENCODING) {
encoder->funcs->dp_set_lane_settings(encoder, link_settings);
}
#else
encoder->funcs->dp_set_lane_settings(encoder, link_settings); encoder->funcs->dp_set_lane_settings(encoder, link_settings);
#endif
} }
void dp_set_hw_test_pattern( void dp_set_hw_test_pattern(
...@@ -304,6 +372,9 @@ void dp_set_hw_test_pattern( ...@@ -304,6 +372,9 @@ void dp_set_hw_test_pattern(
{ {
struct encoder_set_dp_phy_pattern_param pattern_param = {0}; struct encoder_set_dp_phy_pattern_param pattern_param = {0};
struct link_encoder *encoder; struct link_encoder *encoder;
#if defined(CONFIG_DRM_AMD_DC_DCN)
enum dp_link_encoding link_encoding_format = dp_get_link_encoding_format(&link->cur_link_settings);
#endif
/* Access link encoder based on whether it is statically /* Access link encoder based on whether it is statically
* or dynamically assigned to a link. * or dynamically assigned to a link.
...@@ -319,8 +390,27 @@ void dp_set_hw_test_pattern( ...@@ -319,8 +390,27 @@ void dp_set_hw_test_pattern(
pattern_param.custom_pattern_size = custom_pattern_size; pattern_param.custom_pattern_size = custom_pattern_size;
pattern_param.dp_panel_mode = dp_get_panel_mode(link); pattern_param.dp_panel_mode = dp_get_panel_mode(link);
#if defined(CONFIG_DRM_AMD_DC_DCN)
switch (link_encoding_format) {
case DP_128b_132b_ENCODING:
link->hpo_dp_link_enc->funcs->set_link_test_pattern(
link->hpo_dp_link_enc, &pattern_param);
break;
case DP_8b_10b_ENCODING:
ASSERT(encoder);
encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
break;
default:
DC_LOG_ERROR("%s: Unknown link encoding format.", __func__);
break;
}
#else
encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
#endif
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
#undef DC_LOGGER
#endif
void dp_retrain_link_dp_test(struct dc_link *link, void dp_retrain_link_dp_test(struct dc_link *link,
struct dc_link_settings *link_setting, struct dc_link_settings *link_setting,
...@@ -468,7 +558,12 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) ...@@ -468,7 +558,12 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
/* Enable DSC in encoder */ /* Enable DSC in encoder */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)
&& !is_dp_128b_132b_signal(pipe_ctx)) {
#else
if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
#endif
DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
dsc_optc_config_log(dsc, &dsc_optc_cfg); dsc_optc_config_log(dsc, &dsc_optc_cfg);
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
...@@ -495,6 +590,14 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) ...@@ -495,6 +590,14 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
/* disable DSC in stream encoder */ /* disable DSC in stream encoder */
if (dc_is_dp_signal(stream->signal)) { if (dc_is_dp_signal(stream->signal)) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.hpo_dp_stream_enc,
false,
NULL);
else
#endif
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.stream_enc,
...@@ -562,6 +665,14 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) ...@@ -562,6 +665,14 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
if (dc_is_dp_signal(stream->signal)) { if (dc_is_dp_signal(stream->signal)) {
DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.hpo_dp_stream_enc,
true,
&dsc_packed_pps[0]);
else
#endif
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.stream_enc,
true, true,
...@@ -570,6 +681,14 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) ...@@ -570,6 +681,14 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
} else { } else {
/* disable DSC PPS in stream encoder */ /* disable DSC PPS in stream encoder */
if (dc_is_dp_signal(stream->signal)) { if (dc_is_dp_signal(stream->signal)) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.hpo_dp_stream_enc,
false,
NULL);
else
#endif
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.stream_enc, false, NULL); pipe_ctx->stream_res.stream_enc, false, NULL);
} }
...@@ -593,3 +712,167 @@ bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) ...@@ -593,3 +712,167 @@ bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
return true; return true;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
#undef DC_LOGGER
#define DC_LOGGER \
link->ctx->logger
static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link)
{
switch (link->link_enc->transmitter) {
case TRANSMITTER_UNIPHY_A:
return PHYD32CLKA;
case TRANSMITTER_UNIPHY_B:
return PHYD32CLKB;
case TRANSMITTER_UNIPHY_C:
return PHYD32CLKC;
case TRANSMITTER_UNIPHY_D:
return PHYD32CLKD;
case TRANSMITTER_UNIPHY_E:
return PHYD32CLKE;
default:
return PHYD32CLKA;
}
}
void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *link_settings)
{
const struct dc *dc = link->dc;
enum phyd32clk_clock_source phyd32clk;
/* Enable PHY PLL at target bit rate
* UHBR10 = 10Gbps (SYMCLK32 = 312.5MHz)
* UBR13.5 = 13.5Gbps (SYMCLK32 = 421.875MHz)
* UHBR20 = 20Gbps (SYMCLK32 = 625MHz)
*/
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
switch (link_settings->link_rate) {
case LINK_RATE_UHBR10:
dm_set_phyd32clk(dc->ctx, 312500);
break;
case LINK_RATE_UHBR13_5:
dm_set_phyd32clk(dc->ctx, 412875);
break;
case LINK_RATE_UHBR20:
dm_set_phyd32clk(dc->ctx, 625000);
break;
default:
return;
}
} else {
/* DP2.0 HW: call transmitter control to enable PHY */
link->hpo_dp_link_enc->funcs->enable_link_phy(
link->hpo_dp_link_enc,
link_settings,
link->link_enc->transmitter);
}
/* DCCG muxing and DTBCLK DTO */
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
dc->res_pool->dccg->funcs->set_physymclk(
dc->res_pool->dccg,
link->link_enc_hw_inst,
PHYSYMCLK_FORCE_SRC_PHYD32CLK,
true);
phyd32clk = get_phyd32clk_src(link);
dc->res_pool->dccg->funcs->enable_symclk32_le(
dc->res_pool->dccg,
link->hpo_dp_link_enc->inst,
phyd32clk);
link->hpo_dp_link_enc->funcs->link_enable(
link->hpo_dp_link_enc,
link_settings->lane_count);
}
}
void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal)
{
const struct dc *dc = link->dc;
link->hpo_dp_link_enc->funcs->link_disable(link->hpo_dp_link_enc);
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
dc->res_pool->dccg->funcs->disable_symclk32_le(
dc->res_pool->dccg,
link->hpo_dp_link_enc->inst);
dc->res_pool->dccg->funcs->set_physymclk(
dc->res_pool->dccg,
link->link_enc_hw_inst,
PHYSYMCLK_FORCE_SRC_SYMCLK,
false);
dm_set_phyd32clk(dc->ctx, 0);
} else {
/* DP2.0 HW: call transmitter control to disable PHY */
link->hpo_dp_link_enc->funcs->disable_link_phy(
link->hpo_dp_link_enc,
signal);
}
}
void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable)
{
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc *dc = pipe_ctx->stream->ctx->dc;
struct pipe_ctx *odm_pipe;
int odm_combine_num_segments = 1;
enum phyd32clk_clock_source phyd32clk;
if (enable) {
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
odm_combine_num_segments++;
dc->res_pool->dccg->funcs->set_dpstreamclk(
dc->res_pool->dccg,
DTBCLK0,
pipe_ctx->stream_res.tg->inst);
phyd32clk = get_phyd32clk_src(stream->link);
dc->res_pool->dccg->funcs->enable_symclk32_se(
dc->res_pool->dccg,
pipe_ctx->stream_res.hpo_dp_stream_enc->inst,
phyd32clk);
dc->res_pool->dccg->funcs->set_dtbclk_dto(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
stream->phy_pix_clk,
odm_combine_num_segments,
&stream->timing);
} else {
dc->res_pool->dccg->funcs->set_dtbclk_dto(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
0,
0,
&stream->timing);
dc->res_pool->dccg->funcs->disable_symclk32_se(
dc->res_pool->dccg,
pipe_ctx->stream_res.hpo_dp_stream_enc->inst);
dc->res_pool->dccg->funcs->set_dpstreamclk(
dc->res_pool->dccg,
REFCLK,
pipe_ctx->stream_res.tg->inst);
}
}
void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link)
{
const struct dc *dc = link->dc;
struct dc_state *state = dc->current_state;
uint8_t i;
for (i = 0; i < MAX_PIPES; i++) {
if (state->res_ctx.pipe_ctx[i].stream_res.hpo_dp_stream_enc &&
state->res_ctx.pipe_ctx[i].stream &&
state->res_ctx.pipe_ctx[i].stream->link == link &&
!state->res_ctx.pipe_ctx[i].stream->dpms_off) {
setup_dp_hpo_stream(&state->res_ctx.pipe_ctx[i], false);
}
}
}
#undef DC_LOGGER
#endif
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "set_mode_types.h" #include "set_mode_types.h"
#include "virtual/virtual_stream_encoder.h" #include "virtual/virtual_stream_encoder.h"
#include "dpcd_defs.h" #include "dpcd_defs.h"
#include "dc_link_dp.h"
#if defined(CONFIG_DRM_AMD_DC_SI) #if defined(CONFIG_DRM_AMD_DC_SI)
#include "dce60/dce60_resource.h" #include "dce60/dce60_resource.h"
...@@ -346,6 +347,29 @@ bool resource_construct( ...@@ -346,6 +347,29 @@ bool resource_construct(
} }
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
pool->hpo_dp_stream_enc_count = 0;
if (create_funcs->create_hpo_dp_stream_encoder) {
for (i = 0; i < caps->num_hpo_dp_stream_encoder; i++) {
pool->hpo_dp_stream_enc[i] = create_funcs->create_hpo_dp_stream_encoder(i+ENGINE_ID_HPO_DP_0, ctx);
if (pool->hpo_dp_stream_enc[i] == NULL)
DC_ERR("DC: failed to create HPO DP stream encoder!\n");
pool->hpo_dp_stream_enc_count++;
}
}
pool->hpo_dp_link_enc_count = 0;
if (create_funcs->create_hpo_dp_link_encoder) {
for (i = 0; i < caps->num_hpo_dp_link_encoder; i++) {
pool->hpo_dp_link_enc[i] = create_funcs->create_hpo_dp_link_encoder(i, ctx);
if (pool->hpo_dp_link_enc[i] == NULL)
DC_ERR("DC: failed to create HPO DP link encoder!\n");
pool->hpo_dp_link_enc_count++;
}
}
#endif
#if defined(CONFIG_DRM_AMD_DC_DCN) #if defined(CONFIG_DRM_AMD_DC_DCN)
for (i = 0; i < caps->num_mpc_3dlut; i++) { for (i = 0; i < caps->num_mpc_3dlut; i++) {
pool->mpc_lut[i] = dc_create_3dlut_func(); pool->mpc_lut[i] = dc_create_3dlut_func();
...@@ -1665,6 +1689,22 @@ static void update_stream_engine_usage( ...@@ -1665,6 +1689,22 @@ static void update_stream_engine_usage(
} }
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
static void update_hpo_dp_stream_engine_usage(
struct resource_context *res_ctx,
const struct resource_pool *pool,
struct hpo_dp_stream_encoder *hpo_dp_stream_enc,
bool acquired)
{
int i;
for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
if (pool->hpo_dp_stream_enc[i] == hpo_dp_stream_enc)
res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired;
}
}
#endif
/* TODO: release audio object */ /* TODO: release audio object */
void update_audio_usage( void update_audio_usage(
struct resource_context *res_ctx, struct resource_context *res_ctx,
...@@ -1709,6 +1749,26 @@ static int acquire_first_free_pipe( ...@@ -1709,6 +1749,26 @@ static int acquire_first_free_pipe(
return -1; return -1;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for_link(
struct resource_context *res_ctx,
const struct resource_pool *pool,
struct dc_stream_state *stream)
{
int i;
for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
if (!res_ctx->is_hpo_dp_stream_enc_acquired[i] &&
pool->hpo_dp_stream_enc[i]) {
return pool->hpo_dp_stream_enc[i];
}
}
return NULL;
}
#endif
static struct audio *find_first_free_audio( static struct audio *find_first_free_audio(
struct resource_context *res_ctx, struct resource_context *res_ctx,
const struct resource_pool *pool, const struct resource_pool *pool,
...@@ -1799,6 +1859,15 @@ enum dc_status dc_remove_stream_from_ctx( ...@@ -1799,6 +1859,15 @@ enum dc_status dc_remove_stream_from_ctx(
if (dc->res_pool->funcs->link_enc_unassign) if (dc->res_pool->funcs->link_enc_unassign)
dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(del_pipe)) {
update_hpo_dp_stream_engine_usage(
&new_ctx->res_ctx, dc->res_pool,
del_pipe->stream_res.hpo_dp_stream_enc,
false);
}
#endif
if (del_pipe->stream_res.audio) if (del_pipe->stream_res.audio)
update_audio_usage( update_audio_usage(
&new_ctx->res_ctx, &new_ctx->res_ctx,
...@@ -2051,6 +2120,31 @@ enum dc_status resource_map_pool_resources( ...@@ -2051,6 +2120,31 @@ enum dc_status resource_map_pool_resources(
pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.stream_enc,
true); true);
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* Allocate DP HPO Stream Encoder based on signal, hw capabilities
* and link settings
*/
if (dc_is_dp_signal(stream->signal) &&
dc->caps.dp_hpo) {
struct dc_link_settings link_settings = {0};
decide_link_settings(stream, &link_settings);
if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING) {
pipe_ctx->stream_res.hpo_dp_stream_enc =
find_first_free_match_hpo_dp_stream_enc_for_link(
&context->res_ctx, pool, stream);
if (!pipe_ctx->stream_res.hpo_dp_stream_enc)
return DC_NO_STREAM_ENC_RESOURCE;
update_hpo_dp_stream_engine_usage(
&context->res_ctx, pool,
pipe_ctx->stream_res.hpo_dp_stream_enc,
true);
}
}
#endif
/* TODO: Add check if ASIC support and EDID audio */ /* TODO: Add check if ASIC support and EDID audio */
if (!stream->converter_disable_audio && if (!stream->converter_disable_audio &&
dc_is_audio_capable_signal(pipe_ctx->stream->signal) && dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
...@@ -2726,6 +2820,11 @@ bool pipe_need_reprogram( ...@@ -2726,6 +2820,11 @@ bool pipe_need_reprogram(
if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc)
return true; return true;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc)
return true;
#endif
/* DIG link encoder resource assignment for stream changed. */ /* DIG link encoder resource assignment for stream changed. */
if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc) if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc)
return true; return true;
...@@ -2975,3 +3074,22 @@ void get_audio_check(struct audio_info *aud_modes, ...@@ -2975,3 +3074,22 @@ void get_audio_check(struct audio_info *aud_modes,
} }
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder(
const struct resource_pool *pool)
{
uint8_t i;
struct hpo_dp_link_encoder *enc = NULL;
ASSERT(pool->hpo_dp_link_enc_count <= MAX_HPO_DP2_LINK_ENCODERS);
for (i = 0; i < pool->hpo_dp_link_enc_count; i++) {
if (pool->hpo_dp_link_enc[i]->transmitter == TRANSMITTER_UNKNOWN) {
enc = pool->hpo_dp_link_enc[i];
break;
}
}
return enc;
}
#endif
...@@ -183,6 +183,9 @@ struct dc_caps { ...@@ -183,6 +183,9 @@ struct dc_caps {
unsigned int cursor_cache_size; unsigned int cursor_cache_size;
struct dc_plane_cap planes[MAX_PLANES]; struct dc_plane_cap planes[MAX_PLANES];
struct dc_color_caps color; struct dc_color_caps color;
#if defined(CONFIG_DRM_AMD_DC_DCN)
bool dp_hpo;
#endif
bool vbios_lttpr_aware; bool vbios_lttpr_aware;
bool vbios_lttpr_enable; bool vbios_lttpr_enable;
}; };
...@@ -289,7 +292,15 @@ struct dc_cap_funcs { ...@@ -289,7 +292,15 @@ struct dc_cap_funcs {
struct link_training_settings; struct link_training_settings;
#if defined(CONFIG_DRM_AMD_DC_DCN)
union allow_lttpr_non_transparent_mode {
struct {
bool DP1_4A : 1;
bool DP2_0 : 1;
} bits;
unsigned char raw;
};
#endif
/* Structure to hold configuration flags set by dm at dc creation. */ /* Structure to hold configuration flags set by dm at dc creation. */
struct dc_config { struct dc_config {
bool gpu_vm_support; bool gpu_vm_support;
...@@ -302,7 +313,11 @@ struct dc_config { ...@@ -302,7 +313,11 @@ struct dc_config {
bool edp_no_power_sequencing; bool edp_no_power_sequencing;
bool force_enum_edp; bool force_enum_edp;
bool forced_clocks; bool forced_clocks;
#if defined(CONFIG_DRM_AMD_DC_DCN)
union allow_lttpr_non_transparent_mode allow_lttpr_non_transparent_mode;
#else
bool allow_lttpr_non_transparent_mode; bool allow_lttpr_non_transparent_mode;
#endif
bool multi_mon_pp_mclk_switch; bool multi_mon_pp_mclk_switch;
bool disable_dmcu; bool disable_dmcu;
bool enable_4to1MPC; bool enable_4to1MPC;
...@@ -614,6 +629,10 @@ struct dc_debug_options { ...@@ -614,6 +629,10 @@ struct dc_debug_options {
bool enable_dmcub_surface_flip; bool enable_dmcub_surface_flip;
bool usbc_combo_phy_reset_wa; bool usbc_combo_phy_reset_wa;
bool enable_dram_clock_change_one_display_vactive; bool enable_dram_clock_change_one_display_vactive;
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* TODO - remove once tested */
bool legacy_dp2_lt;
#endif
union mem_low_power_enable_options enable_mem_low_power; union mem_low_power_enable_options enable_mem_low_power;
bool force_vblank_alignment; bool force_vblank_alignment;
...@@ -1146,6 +1165,12 @@ struct dpcd_caps { ...@@ -1146,6 +1165,12 @@ struct dpcd_caps {
struct dc_lttpr_caps lttpr_caps; struct dc_lttpr_caps lttpr_caps;
struct psr_caps psr_caps; struct psr_caps psr_caps;
#if defined(CONFIG_DRM_AMD_DC_DCN)
union dp_128b_132b_supported_link_rates dp_128b_132b_supported_link_rates;
union dp_main_line_channel_coding_cap channel_coding_cap;
union dp_sink_video_fallback_formats fallback_formats;
union dp_fec_capability1 fec_cap1;
#endif
}; };
union dpcd_sink_ext_caps { union dpcd_sink_ext_caps {
......
...@@ -53,7 +53,17 @@ enum dc_link_rate { ...@@ -53,7 +53,17 @@ enum dc_link_rate {
LINK_RATE_RBR2 = 0x0C, // Rate_5 (RBR2)- 3.24 Gbps/Lane LINK_RATE_RBR2 = 0x0C, // Rate_5 (RBR2)- 3.24 Gbps/Lane
LINK_RATE_RATE_6 = 0x10, // Rate_6 - 4.32 Gbps/Lane LINK_RATE_RATE_6 = 0x10, // Rate_6 - 4.32 Gbps/Lane
LINK_RATE_HIGH2 = 0x14, // Rate_7 (HBR2)- 5.40 Gbps/Lane LINK_RATE_HIGH2 = 0x14, // Rate_7 (HBR2)- 5.40 Gbps/Lane
#if defined(CONFIG_DRM_AMD_DC_DCN)
LINK_RATE_HIGH3 = 0x1E, // Rate_8 (HBR3)- 8.10 Gbps/Lane
/* Starting from DP2.0 link rate enum directly represents actual
* link rate value in unit of 10 mbps
*/
LINK_RATE_UHBR10 = 1000, // UHBR10 - 10.0 Gbps/Lane
LINK_RATE_UHBR13_5 = 1350, // UHBR13.5 - 13.5 Gbps/Lane
LINK_RATE_UHBR20 = 2000, // UHBR10 - 20.0 Gbps/Lane
#else
LINK_RATE_HIGH3 = 0x1E // Rate_8 (HBR3)- 8.10 Gbps/Lane LINK_RATE_HIGH3 = 0x1E // Rate_8 (HBR3)- 8.10 Gbps/Lane
#endif
}; };
enum dc_link_spread { enum dc_link_spread {
...@@ -90,17 +100,47 @@ enum dc_post_cursor2 { ...@@ -90,17 +100,47 @@ enum dc_post_cursor2 {
POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3, POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3,
}; };
#if defined(CONFIG_DRM_AMD_DC_DCN)
enum dc_dp_ffe_preset_level {
DP_FFE_PRESET_LEVEL0 = 0,
DP_FFE_PRESET_LEVEL1,
DP_FFE_PRESET_LEVEL2,
DP_FFE_PRESET_LEVEL3,
DP_FFE_PRESET_LEVEL4,
DP_FFE_PRESET_LEVEL5,
DP_FFE_PRESET_LEVEL6,
DP_FFE_PRESET_LEVEL7,
DP_FFE_PRESET_LEVEL8,
DP_FFE_PRESET_LEVEL9,
DP_FFE_PRESET_LEVEL10,
DP_FFE_PRESET_LEVEL11,
DP_FFE_PRESET_LEVEL12,
DP_FFE_PRESET_LEVEL13,
DP_FFE_PRESET_LEVEL14,
DP_FFE_PRESET_LEVEL15,
DP_FFE_PRESET_MAX_LEVEL = DP_FFE_PRESET_LEVEL15,
};
#endif
enum dc_dp_training_pattern { enum dc_dp_training_pattern {
DP_TRAINING_PATTERN_SEQUENCE_1 = 0, DP_TRAINING_PATTERN_SEQUENCE_1 = 0,
DP_TRAINING_PATTERN_SEQUENCE_2, DP_TRAINING_PATTERN_SEQUENCE_2,
DP_TRAINING_PATTERN_SEQUENCE_3, DP_TRAINING_PATTERN_SEQUENCE_3,
DP_TRAINING_PATTERN_SEQUENCE_4, DP_TRAINING_PATTERN_SEQUENCE_4,
DP_TRAINING_PATTERN_VIDEOIDLE, DP_TRAINING_PATTERN_VIDEOIDLE,
#if defined(CONFIG_DRM_AMD_DC_DCN)
DP_128b_132b_TPS1,
DP_128b_132b_TPS2,
DP_128b_132b_TPS2_CDS,
#endif
}; };
enum dp_link_encoding { enum dp_link_encoding {
DP_UNKNOWN_ENCODING = 0, DP_UNKNOWN_ENCODING = 0,
DP_8b_10b_ENCODING = 1, DP_8b_10b_ENCODING = 1,
#if defined(CONFIG_DRM_AMD_DC_DCN)
DP_128b_132b_ENCODING = 2,
#endif
}; };
struct dc_link_settings { struct dc_link_settings {
...@@ -112,10 +152,26 @@ struct dc_link_settings { ...@@ -112,10 +152,26 @@ struct dc_link_settings {
bool dpcd_source_device_specific_field_support; bool dpcd_source_device_specific_field_support;
}; };
#if defined(CONFIG_DRM_AMD_DC_DCN)
union dc_dp_ffe_preset {
struct {
uint8_t level : 4;
uint8_t reserved : 1;
uint8_t no_preshoot : 1;
uint8_t no_deemphasis : 1;
uint8_t method2 : 1;
} settings;
uint8_t raw;
};
#endif
struct dc_lane_settings { struct dc_lane_settings {
enum dc_voltage_swing VOLTAGE_SWING; enum dc_voltage_swing VOLTAGE_SWING;
enum dc_pre_emphasis PRE_EMPHASIS; enum dc_pre_emphasis PRE_EMPHASIS;
enum dc_post_cursor2 POST_CURSOR2; enum dc_post_cursor2 POST_CURSOR2;
#if defined(CONFIG_DRM_AMD_DC_DCN)
union dc_dp_ffe_preset FFE_PRESET;
#endif
}; };
struct dc_link_training_settings { struct dc_link_training_settings {
...@@ -127,6 +183,9 @@ struct dc_link_training_overrides { ...@@ -127,6 +183,9 @@ struct dc_link_training_overrides {
enum dc_voltage_swing *voltage_swing; enum dc_voltage_swing *voltage_swing;
enum dc_pre_emphasis *pre_emphasis; enum dc_pre_emphasis *pre_emphasis;
enum dc_post_cursor2 *post_cursor2; enum dc_post_cursor2 *post_cursor2;
#if defined(CONFIG_DRM_AMD_DC_DCN)
union dc_dp_ffe_preset *ffe_preset;
#endif
uint16_t *cr_pattern_time; uint16_t *cr_pattern_time;
uint16_t *eq_pattern_time; uint16_t *eq_pattern_time;
...@@ -140,6 +199,16 @@ struct dc_link_training_overrides { ...@@ -140,6 +199,16 @@ struct dc_link_training_overrides {
bool *fec_enable; bool *fec_enable;
}; };
#if defined(CONFIG_DRM_AMD_DC_DCN)
union payload_table_update_status {
struct {
uint8_t VC_PAYLOAD_TABLE_UPDATED:1;
uint8_t ACT_HANDLED:1;
} bits;
uint8_t raw;
};
#endif
union dpcd_rev { union dpcd_rev {
struct { struct {
uint8_t MINOR:4; uint8_t MINOR:4;
...@@ -227,7 +296,14 @@ union lane_align_status_updated { ...@@ -227,7 +296,14 @@ union lane_align_status_updated {
struct { struct {
uint8_t INTERLANE_ALIGN_DONE:1; uint8_t INTERLANE_ALIGN_DONE:1;
uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1;
#if defined(CONFIG_DRM_AMD_DC_DCN)
uint8_t EQ_INTERLANE_ALIGN_DONE_128b_132b:1;
uint8_t CDS_INTERLANE_ALIGN_DONE_128b_132b:1;
uint8_t LT_FAILED_128b_132b:1;
uint8_t RESERVED:1;
#else
uint8_t RESERVED:4; uint8_t RESERVED:4;
#endif
uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1;
uint8_t LINK_STATUS_UPDATED:1; uint8_t LINK_STATUS_UPDATED:1;
} bits; } bits;
...@@ -240,6 +316,12 @@ union lane_adjust { ...@@ -240,6 +316,12 @@ union lane_adjust {
uint8_t PRE_EMPHASIS_LANE:2; uint8_t PRE_EMPHASIS_LANE:2;
uint8_t RESERVED:4; uint8_t RESERVED:4;
} bits; } bits;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct {
uint8_t PRESET_VALUE :4;
uint8_t RESERVED :4;
} tx_ffe;
#endif
uint8_t raw; uint8_t raw;
}; };
...@@ -269,6 +351,12 @@ union dpcd_training_lane { ...@@ -269,6 +351,12 @@ union dpcd_training_lane {
uint8_t MAX_PRE_EMPHASIS_REACHED:1; uint8_t MAX_PRE_EMPHASIS_REACHED:1;
uint8_t RESERVED:2; uint8_t RESERVED:2;
} bits; } bits;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct {
uint8_t PRESET_VALUE :4;
uint8_t RESERVED :4;
} tx_ffe;
#endif
uint8_t raw; uint8_t raw;
}; };
...@@ -551,12 +639,18 @@ union test_response { ...@@ -551,12 +639,18 @@ union test_response {
union phy_test_pattern { union phy_test_pattern {
struct { struct {
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* This field is 7 bits for DP2.0 */
uint8_t PATTERN :7;
uint8_t RESERVED :1;
#else
/* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1
* and 3 bits for DP1.2. * and 3 bits for DP1.2.
*/ */
uint8_t PATTERN :3; uint8_t PATTERN :3;
/* BY speci, bit7:2 is 0 for DP1.1. */ /* BY speci, bit7:2 is 0 for DP1.1. */
uint8_t RESERVED :5; uint8_t RESERVED :5;
#endif
} bits; } bits;
uint8_t raw; uint8_t raw;
}; };
...@@ -634,7 +728,14 @@ union dpcd_fec_capability { ...@@ -634,7 +728,14 @@ union dpcd_fec_capability {
uint8_t UNCORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1; uint8_t UNCORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1;
uint8_t CORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1; uint8_t CORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1;
uint8_t BIT_ERROR_COUNT_CAPABLE:1; uint8_t BIT_ERROR_COUNT_CAPABLE:1;
#if defined(CONFIG_DRM_AMD_DC_DCN)
uint8_t PARITY_BLOCK_ERROR_COUNT_CAPABLE:1;
uint8_t ARITY_BIT_ERROR_COUNT_CAPABLE:1;
uint8_t FEC_RUNNING_INDICATOR_SUPPORTED:1;
uint8_t FEC_ERROR_REPORTING_POLICY_SUPPORTED:1;
#else
uint8_t RESERVED:4; uint8_t RESERVED:4;
#endif
} bits; } bits;
uint8_t raw; uint8_t raw;
}; };
...@@ -758,4 +859,125 @@ struct psr_caps { ...@@ -758,4 +859,125 @@ struct psr_caps {
bool psr_exit_link_training_required; bool psr_exit_link_training_required;
}; };
#if defined(CONFIG_DRM_AMD_DC_DCN)
#define DP_MAIN_LINK_CHANNEL_CODING_CAP 0x006
#define DP_SINK_VIDEO_FALLBACK_FORMATS 0x020
#define DP_FEC_CAPABILITY_1 0x091
#define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0A3
#define DP_DSC_CONFIGURATION 0x161
#define DP_PHY_SQUARE_PATTERN 0x249
#define DP_128b_132b_SUPPORTED_LINK_RATES 0x2215
#define DP_128b_132b_TRAINING_AUX_RD_INTERVAL 0x2216
#define DP_TEST_264BIT_CUSTOM_PATTERN_7_0 0X2230
#define DP_TEST_264BIT_CUSTOM_PATTERN_263_256 0X2250
#define DP_DSC_SUPPORT_AND_DECODER_COUNT 0x2260
#define DP_DSC_MAX_SLICE_COUNT_AND_AGGREGATION_0 0x2270
# define DP_DSC_DECODER_0_MAXIMUM_SLICE_COUNT_MASK (1 << 0)
# define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_MASK (0b111 << 1)
# define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_SHIFT 1
# define DP_DSC_DECODER_COUNT_MASK (0b111 << 5)
# define DP_DSC_DECODER_COUNT_SHIFT 5
#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
#define DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER 0xF0006
#define DP_PHY_REPEATER_128b_132b_RATES 0xF0007
#define DP_128b_132b_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 0xF0022
#define DP_INTRA_HOP_AUX_REPLY_INDICATION (1 << 3)
/* TODO - Use DRM header to replace above once available */
union dp_main_line_channel_coding_cap {
struct {
uint8_t DP_8b_10b_SUPPORTED :1;
uint8_t DP_128b_132b_SUPPORTED :1;
uint8_t RESERVED :6;
} bits;
uint8_t raw;
};
union dp_main_link_channel_coding_lttpr_cap {
struct {
uint8_t DP_128b_132b_SUPPORTED :1;
uint8_t RESERVED :7;
} bits;
uint8_t raw;
};
union dp_128b_132b_supported_link_rates {
struct {
uint8_t UHBR10 :1;
uint8_t UHBR20 :1;
uint8_t UHBR13_5:1;
uint8_t RESERVED:5;
} bits;
uint8_t raw;
};
union dp_128b_132b_supported_lttpr_link_rates {
struct {
uint8_t UHBR10 :1;
uint8_t UHBR13_5:1;
uint8_t UHBR20 :1;
uint8_t RESERVED:5;
} bits;
uint8_t raw;
};
union dp_sink_video_fallback_formats {
struct {
uint8_t dp_1024x768_60Hz_24bpp_support :1;
uint8_t dp_1280x720_60Hz_24bpp_support :1;
uint8_t dp_1920x1080_60Hz_24bpp_support :1;
uint8_t RESERVED :5;
} bits;
uint8_t raw;
};
union dp_fec_capability1 {
struct {
uint8_t AGGREGATED_ERROR_COUNTERS_CAPABLE :1;
uint8_t RESERVED :7;
} bits;
uint8_t raw;
};
struct dp_color_depth_caps {
uint8_t support_6bpc :1;
uint8_t support_8bpc :1;
uint8_t support_10bpc :1;
uint8_t support_12bpc :1;
uint8_t support_16bpc :1;
uint8_t RESERVED :3;
};
struct dp_encoding_format_caps {
uint8_t support_rgb :1;
uint8_t support_ycbcr444:1;
uint8_t support_ycbcr422:1;
uint8_t support_ycbcr420:1;
uint8_t RESERVED :4;
};
union dp_dfp_cap_ext {
struct {
uint8_t supported;
uint8_t max_pixel_rate_in_mps[2];
uint8_t max_video_h_active_width[2];
uint8_t max_video_v_active_height[2];
struct dp_encoding_format_caps encoding_format_caps;
struct dp_color_depth_caps rgb_color_depth_caps;
struct dp_color_depth_caps ycbcr444_color_depth_caps;
struct dp_color_depth_caps ycbcr422_color_depth_caps;
struct dp_color_depth_caps ycbcr420_color_depth_caps;
} fields;
uint8_t raw[12];
};
union dp_128b_132b_training_aux_rd_interval {
struct {
uint8_t VALUE :7;
uint8_t UNIT :1;
} bits;
uint8_t raw;
};
#endif
#endif /* DC_DP_TYPES_H */ #endif /* DC_DP_TYPES_H */
...@@ -154,6 +154,9 @@ struct dc_link { ...@@ -154,6 +154,9 @@ struct dc_link {
struct panel_cntl *panel_cntl; struct panel_cntl *panel_cntl;
struct link_encoder *link_enc; struct link_encoder *link_enc;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct hpo_dp_link_encoder *hpo_dp_link_enc;
#endif
struct graphics_object_id link_id; struct graphics_object_id link_id;
/* Endpoint type distinguishes display endpoints which do not have entries /* Endpoint type distinguishes display endpoints which do not have entries
* in the BIOS connector table from those that do. Helps when tracking link * in the BIOS connector table from those that do. Helps when tracking link
......
...@@ -395,9 +395,27 @@ struct dc_lttpr_caps { ...@@ -395,9 +395,27 @@ struct dc_lttpr_caps {
uint8_t max_link_rate; uint8_t max_link_rate;
uint8_t phy_repeater_cnt; uint8_t phy_repeater_cnt;
uint8_t max_ext_timeout; uint8_t max_ext_timeout;
#if defined(CONFIG_DRM_AMD_DC_DCN)
union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding;
union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates;
#endif
uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1];
}; };
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dc_dongle_dfp_cap_ext {
bool supported;
uint16_t max_pixel_rate_in_mps;
uint16_t max_video_h_active_width;
uint16_t max_video_v_active_height;
struct dp_encoding_format_caps encoding_format_caps;
struct dp_color_depth_caps rgb_color_depth_caps;
struct dp_color_depth_caps ycbcr444_color_depth_caps;
struct dp_color_depth_caps ycbcr422_color_depth_caps;
struct dp_color_depth_caps ycbcr420_color_depth_caps;
};
#endif
struct dc_dongle_caps { struct dc_dongle_caps {
/* dongle type (DP converter, CV smart dongle) */ /* dongle type (DP converter, CV smart dongle) */
enum display_dongle_type dongle_type; enum display_dongle_type dongle_type;
...@@ -411,6 +429,9 @@ struct dc_dongle_caps { ...@@ -411,6 +429,9 @@ struct dc_dongle_caps {
bool is_dp_hdmi_ycbcr420_converter; bool is_dp_hdmi_ycbcr420_converter;
uint32_t dp_hdmi_max_bpc; uint32_t dp_hdmi_max_bpc;
uint32_t dp_hdmi_max_pixel_clk_in_khz; uint32_t dp_hdmi_max_pixel_clk_in_khz;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dc_dongle_dfp_cap_ext dfp_cap_ext;
#endif
}; };
/* Scaling format */ /* Scaling format */
enum scaling_transformation { enum scaling_transformation {
......
...@@ -1108,8 +1108,17 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) ...@@ -1108,8 +1108,17 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
clk_mgr->funcs->enable_pme_wa(clk_mgr); clk_mgr->funcs->enable_pme_wa(clk_mgr);
/* un-mute audio */ /* un-mute audio */
/* TODO: audio should be per stream rather than per link */ /* TODO: audio should be per stream rather than per link */
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.hpo_dp_stream_enc, false);
else
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.stream_enc, false); pipe_ctx->stream_res.stream_enc, false);
#else
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.stream_enc, false);
#endif
if (pipe_ctx->stream_res.audio) if (pipe_ctx->stream_res.audio)
pipe_ctx->stream_res.audio->enabled = true; pipe_ctx->stream_res.audio->enabled = true;
} }
...@@ -1129,14 +1138,32 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) ...@@ -1129,14 +1138,32 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false) if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false)
return; return;
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.hpo_dp_stream_enc, true);
else
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.stream_enc, true);
#else
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
pipe_ctx->stream_res.stream_enc, true); pipe_ctx->stream_res.stream_enc, true);
#endif
if (pipe_ctx->stream_res.audio) { if (pipe_ctx->stream_res.audio) {
pipe_ctx->stream_res.audio->enabled = false; pipe_ctx->stream_res.audio->enabled = false;
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (dc_is_dp_signal(pipe_ctx->stream->signal))
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable(
pipe_ctx->stream_res.hpo_dp_stream_enc);
else
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc);
#else
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
pipe_ctx->stream_res.stream_enc);
#endif
else else
pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc);
...@@ -1166,16 +1193,37 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -1166,16 +1193,37 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc);
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx)) {
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->stop_dp_info_packets(
pipe_ctx->stream_res.hpo_dp_stream_enc);
} else if (dc_is_dp_signal(pipe_ctx->stream->signal))
#else
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (dc_is_dp_signal(pipe_ctx->stream->signal))
#endif
pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets(
pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc);
dc->hwss.disable_audio_stream(pipe_ctx); dc->hwss.disable_audio_stream(pipe_ctx);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx)) {
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->disable(
pipe_ctx->stream_res.hpo_dp_stream_enc);
setup_dp_hpo_stream(pipe_ctx, false);
/* TODO - DP2.0 HW: unmap stream from link encoder here */
} else {
link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc->funcs->connect_dig_be_to_fe(
link->link_enc, link->link_enc,
pipe_ctx->stream_res.stream_enc->id, pipe_ctx->stream_res.stream_enc->id,
false); false);
}
#else
link->link_enc->funcs->connect_dig_be_to_fe(
link->link_enc,
pipe_ctx->stream_res.stream_enc->id,
false);
#endif
} }
...@@ -1210,7 +1258,15 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) ...@@ -1210,7 +1258,15 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
link->dc->hwss.set_abm_immediate_disable(pipe_ctx); link->dc->hwss.set_abm_immediate_disable(pipe_ctx);
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx)) {
/* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_blank(
pipe_ctx->stream_res.hpo_dp_stream_enc);
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
#else
if (dc_is_dp_signal(pipe_ctx->stream->signal)) { 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(pipe_ctx->stream_res.stream_enc);
if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) { if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) {
...@@ -1451,10 +1507,23 @@ static enum dc_status apply_single_controller_ctx_to_hw( ...@@ -1451,10 +1507,23 @@ static enum dc_status apply_single_controller_ctx_to_hw(
build_audio_output(context, pipe_ctx, &audio_output); build_audio_output(context, pipe_ctx, &audio_output);
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (dc_is_dp_signal(pipe_ctx->stream->signal))
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup(
pipe_ctx->stream_res.hpo_dp_stream_enc,
pipe_ctx->stream_res.audio->inst,
&pipe_ctx->stream->audio_info);
else
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
pipe_ctx->stream_res.stream_enc,
pipe_ctx->stream_res.audio->inst,
&pipe_ctx->stream->audio_info);
#else
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.stream_enc,
pipe_ctx->stream_res.audio->inst, pipe_ctx->stream_res.audio->inst,
&pipe_ctx->stream->audio_info); &pipe_ctx->stream->audio_info);
#endif
else else
pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.stream_enc,
...@@ -1469,6 +1538,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( ...@@ -1469,6 +1538,14 @@ static enum dc_status apply_single_controller_ctx_to_hw(
&pipe_ctx->stream->audio_info); &pipe_ctx->stream->audio_info);
} }
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* DCN3.1 FPGA Workaround
* Need to enable HPO DP Stream Encoder before setting OTG master enable.
* To do so, move calling function enable_stream_timing to only be done AFTER calling
* function core_link_enable_stream
*/
if (!(hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx)))
#endif
/* */ /* */
/* Do not touch stream timing on seamless boot optimization. */ /* Do not touch stream timing on seamless boot optimization. */
if (!pipe_ctx->stream->apply_seamless_boot_optimization) if (!pipe_ctx->stream->apply_seamless_boot_optimization)
...@@ -1526,6 +1603,18 @@ static enum dc_status apply_single_controller_ctx_to_hw( ...@@ -1526,6 +1603,18 @@ static enum dc_status apply_single_controller_ctx_to_hw(
if (!stream->dpms_off) if (!stream->dpms_off)
core_link_enable_stream(context, pipe_ctx); core_link_enable_stream(context, pipe_ctx);
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* DCN3.1 FPGA Workaround
* Need to enable HPO DP Stream Encoder before setting OTG master enable.
* To do so, move calling function enable_stream_timing to only be done AFTER calling
* function core_link_enable_stream
*/
if (hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx)) {
if (!pipe_ctx->stream->apply_seamless_boot_optimization)
hws->funcs.enable_stream_timing(pipe_ctx, context, dc);
}
#endif
pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false; pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false;
......
...@@ -1460,5 +1460,14 @@ void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, ...@@ -1460,5 +1460,14 @@ void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc,
if (enc->features.flags.bits.IS_HBR3_CAPABLE) if (enc->features.flags.bits.IS_HBR3_CAPABLE)
max_link_cap.link_rate = LINK_RATE_HIGH3; max_link_cap.link_rate = LINK_RATE_HIGH3;
if (enc->features.flags.bits.IS_UHBR10_CAPABLE)
max_link_cap.link_rate = LINK_RATE_UHBR10;
if (enc->features.flags.bits.IS_UHBR13_5_CAPABLE)
max_link_cap.link_rate = LINK_RATE_UHBR13_5;
if (enc->features.flags.bits.IS_UHBR20_CAPABLE)
max_link_cap.link_rate = LINK_RATE_UHBR20;
*link_settings = max_link_cap; *link_settings = max_link_cap;
} }
...@@ -2135,7 +2135,12 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx, ...@@ -2135,7 +2135,12 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
params.link_settings.link_rate = link_settings->link_rate; params.link_settings.link_rate = link_settings->link_rate;
if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (is_dp_128b_132b_signal(pipe_ctx)) {
/* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_unblank(
pipe_ctx->stream_res.hpo_dp_stream_enc,
pipe_ctx->stream_res.tg->inst);
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1) if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1)
params.timing.pix_clk_100hz /= 2; params.timing.pix_clk_100hz /= 2;
pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine( pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
...@@ -2380,8 +2385,19 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) ...@@ -2380,8 +2385,19 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
* disconnect them during disable_stream * disconnect them during disable_stream
* BY this, it is logic clean to separate stream and link * BY this, it is logic clean to separate stream and link
*/ */
link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, if (is_dp_128b_132b_signal(pipe_ctx)) {
pipe_ctx->stream_res.stream_enc->id, true); setup_dp_hpo_stream(pipe_ctx, true);
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->enable_stream(
pipe_ctx->stream_res.hpo_dp_stream_enc);
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->map_stream_to_link(
pipe_ctx->stream_res.hpo_dp_stream_enc,
pipe_ctx->stream_res.hpo_dp_stream_enc->inst,
link->hpo_dp_link_enc->inst);
}
if (!is_dp_128b_132b_signal(pipe_ctx))
link->link_enc->funcs->connect_dig_be_to_fe(
link->link_enc, pipe_ctx->stream_res.stream_enc->id, true);
if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) { if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) {
if (link->dc->hwss.program_dmdata_engine) if (link->dc->hwss.program_dmdata_engine)
...@@ -2406,7 +2422,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) ...@@ -2406,7 +2422,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
/* enable audio only within mode set */ /* enable audio only within mode set */
if (pipe_ctx->stream_res.audio != NULL) { if (pipe_ctx->stream_res.audio != NULL) {
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (is_dp_128b_132b_signal(pipe_ctx))
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.hpo_dp_stream_enc);
else if (dc_is_dp_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
} }
} }
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
#include "dcn20_dccg.h" #include "dcn20_dccg.h"
#include "dcn20_vmid.h" #include "dcn20_vmid.h"
#include "dc_link_ddc.h" #include "dc_link_ddc.h"
#include "dc_link_dp.h"
#include "dce/dce_panel_cntl.h" #include "dce/dce_panel_cntl.h"
#include "navi10_ip_offset.h" #include "navi10_ip_offset.h"
...@@ -1604,6 +1605,7 @@ static void get_pixel_clock_parameters( ...@@ -1604,6 +1605,7 @@ static void get_pixel_clock_parameters(
pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->signal_type = pipe_ctx->stream->signal;
pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1;
/* TODO: un-hardcode*/ /* TODO: un-hardcode*/
/* TODO - DP2.0 HW: calculate requested_sym_clk for UHBR rates */
pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
LINK_RATE_REF_FREQ_IN_KHZ; LINK_RATE_REF_FREQ_IN_KHZ;
pixel_clk_params->flags.ENABLE_SS = 0; pixel_clk_params->flags.ENABLE_SS = 0;
...@@ -3044,6 +3046,8 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) ...@@ -3044,6 +3046,8 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context)
for (i = 0; i < dc->res_pool->pipe_count; i++) { for (i = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream) if (!context->res_ctx.pipe_ctx[i].stream)
continue; continue;
if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i]))
return true;
} }
return false; return false;
} }
......
...@@ -561,11 +561,6 @@ static const struct dcn10_link_enc_mask le_mask = { ...@@ -561,11 +561,6 @@ static const struct dcn10_link_enc_mask le_mask = {
DPCS_DCN31_MASK_SH_LIST(_MASK) DPCS_DCN31_MASK_SH_LIST(_MASK)
}; };
#define dpp_regs(id)\
[id] = {\
DPP_REG_LIST_DCN30(id),\
}
#define hpo_dp_stream_encoder_reg_list(id)\ #define hpo_dp_stream_encoder_reg_list(id)\
[id] = {\ [id] = {\
DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\
...@@ -609,6 +604,11 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { ...@@ -609,6 +604,11 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = {
DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK)
}; };
#define dpp_regs(id)\
[id] = {\
DPP_REG_LIST_DCN30(id),\
}
static const struct dcn3_dpp_registers dpp_regs[] = { static const struct dcn3_dpp_registers dpp_regs[] = {
dpp_regs(0), dpp_regs(0),
dpp_regs(1), dpp_regs(1),
...@@ -1449,6 +1449,13 @@ static struct dce_hwseq *dcn31_hwseq_create( ...@@ -1449,6 +1449,13 @@ static struct dce_hwseq *dcn31_hwseq_create(
hws->regs = &hwseq_reg; hws->regs = &hwseq_reg;
hws->shifts = &hwseq_shift; hws->shifts = &hwseq_shift;
hws->masks = &hwseq_mask; hws->masks = &hwseq_mask;
/* DCN3.1 FPGA Workaround
* Need to enable HPO DP Stream Encoder before setting OTG master enable.
* To do so, move calling function enable_stream_timing to only be done AFTER calling
* function core_link_enable_stream
*/
if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
hws->wa.dp_hpo_and_otg_sequence = true;
} }
return hws; return hws;
} }
...@@ -2102,6 +2109,7 @@ static bool dcn31_resource_construct( ...@@ -2102,6 +2109,7 @@ static bool dcn31_resource_construct(
dc->caps.max_slave_rgb_planes = 1; dc->caps.max_slave_rgb_planes = 1;
dc->caps.post_blend_color_processing = true; dc->caps.post_blend_color_processing = true;
dc->caps.force_dp_tps4_for_cp2520 = true; dc->caps.force_dp_tps4_for_cp2520 = true;
dc->caps.dp_hpo = true;
dc->caps.extended_aux_timeout_support = true; dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true; dc->caps.dmcub_support = true;
dc->caps.is_apu = true; dc->caps.is_apu = true;
......
...@@ -37,6 +37,7 @@ struct cp_psp_stream_config { ...@@ -37,6 +37,7 @@ struct cp_psp_stream_config {
uint8_t phy_idx; uint8_t phy_idx;
uint8_t assr_enabled; uint8_t assr_enabled;
uint8_t mst_enabled; uint8_t mst_enabled;
uint8_t dp2_enabled;
void *dm_stream_ctx; void *dm_stream_ctx;
bool dpms_off; bool dpms_off;
}; };
......
...@@ -160,6 +160,8 @@ void dm_set_dcn_clocks( ...@@ -160,6 +160,8 @@ void dm_set_dcn_clocks(
struct dc_context *ctx, struct dc_context *ctx,
struct dc_clocks *clks); struct dc_clocks *clks);
void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz);
bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable); bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable);
void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us); void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define LINK_TRAINING_RETRY_DELAY 50 /* ms */ #define LINK_TRAINING_RETRY_DELAY 50 /* ms */
#define LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD 3200 /*us*/ #define LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD 3200 /*us*/
#define LINK_AUX_DEFAULT_TIMEOUT_PERIOD 552 /*us*/ #define LINK_AUX_DEFAULT_TIMEOUT_PERIOD 552 /*us*/
#define MAX_MTP_SLOT_COUNT 64
#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50 #define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
#define TRAINING_AUX_RD_INTERVAL 100 //us #define TRAINING_AUX_RD_INTERVAL 100 //us
...@@ -189,5 +190,26 @@ enum dc_status dpcd_configure_lttpr_mode( ...@@ -189,5 +190,26 @@ enum dc_status dpcd_configure_lttpr_mode(
struct link_training_settings *lt_settings); struct link_training_settings *lt_settings);
enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings); enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings);
bool dpcd_write_128b_132b_sst_payload_allocation_table(
const struct dc_stream_state *stream,
struct dc_link *link,
struct link_mst_stream_allocation_table *proposed_table,
bool allocate);
enum dc_status dpcd_configure_channel_coding(
struct dc_link *link,
struct link_training_settings *lt_settings);
bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link);
struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(
const struct dc_stream_state *stream,
const struct dc_link *link);
void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *link_settings);
void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal);
void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable);
bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx);
void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link);
bool dp_retrieve_lttpr_cap(struct dc_link *link); bool dp_retrieve_lttpr_cap(struct dc_link *link);
#endif /* __DC_LINK_DP_H__ */ #endif /* __DC_LINK_DP_H__ */
...@@ -41,6 +41,9 @@ struct dce_hwseq_wa { ...@@ -41,6 +41,9 @@ struct dce_hwseq_wa {
bool DEGVIDCN10_254; bool DEGVIDCN10_254;
bool DEGVIDCN21; bool DEGVIDCN21;
bool disallow_self_refresh_during_multi_plane_transition; bool disallow_self_refresh_during_multi_plane_transition;
#if defined(CONFIG_DRM_AMD_DC_DCN)
bool dp_hpo_and_otg_sequence;
#endif
}; };
struct hwseq_wa_state { struct hwseq_wa_state {
......
...@@ -200,4 +200,9 @@ int get_num_mpc_splits(struct pipe_ctx *pipe); ...@@ -200,4 +200,9 @@ int get_num_mpc_splits(struct pipe_ctx *pipe);
int get_num_odm_splits(struct pipe_ctx *pipe); int get_num_odm_splits(struct pipe_ctx *pipe);
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder(
const struct resource_pool *pool);
#endif
#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */
...@@ -80,6 +80,15 @@ enum dpcd_phy_test_patterns { ...@@ -80,6 +80,15 @@ enum dpcd_phy_test_patterns {
PHY_TEST_PATTERN_CP2520_1, PHY_TEST_PATTERN_CP2520_1,
PHY_TEST_PATTERN_CP2520_2, PHY_TEST_PATTERN_CP2520_2,
PHY_TEST_PATTERN_CP2520_3, /* same as TPS4 */ PHY_TEST_PATTERN_CP2520_3, /* same as TPS4 */
PHY_TEST_PATTERN_128b_132b_TPS1 = 0x8,
PHY_TEST_PATTERN_128b_132b_TPS2 = 0x10,
PHY_TEST_PATTERN_PRBS9 = 0x18,
PHY_TEST_PATTERN_PRBS11 = 0x20,
PHY_TEST_PATTERN_PRBS15 = 0x28,
PHY_TEST_PATTERN_PRBS23 = 0x30,
PHY_TEST_PATTERN_PRBS31 = 0x38,
PHY_TEST_PATTERN_264BIT_CUSTOM = 0x40,
PHY_TEST_PATTERN_SQUARE_PULSE = 0x48,
}; };
enum dpcd_test_dyn_range { enum dpcd_test_dyn_range {
...@@ -135,7 +144,14 @@ enum dpcd_training_patterns { ...@@ -135,7 +144,14 @@ enum dpcd_training_patterns {
DPCD_TRAINING_PATTERN_1, DPCD_TRAINING_PATTERN_1,
DPCD_TRAINING_PATTERN_2, DPCD_TRAINING_PATTERN_2,
DPCD_TRAINING_PATTERN_3, DPCD_TRAINING_PATTERN_3,
#if defined(CONFIG_DRM_AMD_DC_DCN)
DPCD_TRAINING_PATTERN_4 = 7,
DPCD_128b_132b_TPS1 = 1,
DPCD_128b_132b_TPS2 = 2,
DPCD_128b_132b_TPS2_CDS = 3,
#else
DPCD_TRAINING_PATTERN_4 = 7 DPCD_TRAINING_PATTERN_4 = 7
#endif
}; };
/* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus /* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus
......
...@@ -53,7 +53,11 @@ enum edp_revision { ...@@ -53,7 +53,11 @@ enum edp_revision {
}; };
enum { enum {
LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/ LINK_RATE_REF_FREQ_IN_KHZ = 27000, /*27MHz*/
BITS_PER_DP_BYTE = 10,
DATA_EFFICIENCY_8b_10b_x10000 = 8000, /* 80% data efficiency */
DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100 = 97, /* 97% data efficiency when FEC is enabled */
DATA_EFFICIENCY_128b_132b_x10000 = 9646, /* 96.71% data efficiency x 99.75% downspread factor */
}; };
enum link_training_result { enum link_training_result {
...@@ -70,6 +74,12 @@ enum link_training_result { ...@@ -70,6 +74,12 @@ enum link_training_result {
LINK_TRAINING_LINK_LOSS, LINK_TRAINING_LINK_LOSS,
/* Abort link training (because sink unplugged) */ /* Abort link training (because sink unplugged) */
LINK_TRAINING_ABORT, LINK_TRAINING_ABORT,
#if defined(CONFIG_DRM_AMD_DC_DCN)
DP_128b_132b_LT_FAILED,
DP_128b_132b_MAX_LOOP_COUNT_REACHED,
DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT,
DP_128b_132b_CDS_DONE_TIMEOUT,
#endif
}; };
enum lttpr_mode { enum lttpr_mode {
...@@ -86,11 +96,23 @@ struct link_training_settings { ...@@ -86,11 +96,23 @@ struct link_training_settings {
enum dc_pre_emphasis *pre_emphasis; enum dc_pre_emphasis *pre_emphasis;
enum dc_post_cursor2 *post_cursor2; enum dc_post_cursor2 *post_cursor2;
bool should_set_fec_ready; bool should_set_fec_ready;
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* TODO - factor lane_settings out because it changes during LT */
union dc_dp_ffe_preset *ffe_preset;
#endif
uint16_t cr_pattern_time; uint16_t cr_pattern_time;
uint16_t eq_pattern_time; uint16_t eq_pattern_time;
uint16_t cds_pattern_time;
enum dc_dp_training_pattern pattern_for_cr; enum dc_dp_training_pattern pattern_for_cr;
enum dc_dp_training_pattern pattern_for_eq; enum dc_dp_training_pattern pattern_for_eq;
#if defined(CONFIG_DRM_AMD_DC_DCN)
enum dc_dp_training_pattern pattern_for_cds;
uint32_t eq_wait_time_limit;
uint8_t eq_loop_count_limit;
uint32_t cds_wait_time_limit;
#endif
bool enhanced_framing; bool enhanced_framing;
bool allow_invalid_msa_timing_param; bool allow_invalid_msa_timing_param;
......
...@@ -72,6 +72,9 @@ ...@@ -72,6 +72,9 @@
#define DC_LOG_DSC(...) DRM_DEBUG_KMS(__VA_ARGS__) #define DC_LOG_DSC(...) DRM_DEBUG_KMS(__VA_ARGS__)
#define DC_LOG_SMU(...) pr_debug("[SMU_MSG]:"__VA_ARGS__) #define DC_LOG_SMU(...) pr_debug("[SMU_MSG]:"__VA_ARGS__)
#define DC_LOG_DWB(...) DRM_DEBUG_KMS(__VA_ARGS__) #define DC_LOG_DWB(...) DRM_DEBUG_KMS(__VA_ARGS__)
#if defined(CONFIG_DRM_AMD_DC_DCN)
#define DC_LOG_DP2(...) DRM_DEBUG_KMS(__VA_ARGS__)
#endif
struct dal_logger; struct dal_logger;
...@@ -123,6 +126,9 @@ enum dc_log_type { ...@@ -123,6 +126,9 @@ enum dc_log_type {
LOG_MAX_HW_POINTS, LOG_MAX_HW_POINTS,
LOG_ALL_TF_CHANNELS, LOG_ALL_TF_CHANNELS,
LOG_SAMPLE_1DLUT, LOG_SAMPLE_1DLUT,
#if defined(CONFIG_DRM_AMD_DC_DCN)
LOG_DP2,
#endif
LOG_SECTION_TOTAL_COUNT LOG_SECTION_TOTAL_COUNT
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment