aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/link
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/link')
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c66
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_factory.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c30
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c51
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c53
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c3
13 files changed, 182 insertions, 135 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
index 1328a0ade342..50459d7a0f85 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
@@ -46,9 +46,15 @@ void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx)
if (dc_is_dp_signal(pipe_ctx->stream->signal))
pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence(pipe_ctx->stream->link,
DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE);
+ if (stream_enc->funcs->enable_stream)
+ stream_enc->funcs->enable_stream(stream_enc,
+ pipe_ctx->stream->signal, true);
if (stream_enc->funcs->map_stream_to_link)
stream_enc->funcs->map_stream_to_link(stream_enc,
stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A);
+ if (stream_enc->funcs->set_input_mode)
+ stream_enc->funcs->set_input_mode(stream_enc,
+ pipe_ctx->stream_res.pix_clk_params.dio_se_pix_per_cycle);
if (stream_enc->funcs->enable_fifo)
stream_enc->funcs->enable_fifo(stream_enc);
}
@@ -60,7 +66,11 @@ void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx)
if (stream_enc && stream_enc->funcs->disable_fifo)
stream_enc->funcs->disable_fifo(stream_enc);
-
+ if (stream_enc->funcs->set_input_mode)
+ stream_enc->funcs->set_input_mode(stream_enc, 0);
+ if (stream_enc->funcs->enable_stream)
+ stream_enc->funcs->enable_stream(stream_enc,
+ pipe_ctx->stream->signal, false);
link_enc->funcs->connect_dig_be_to_fe(
link_enc,
pipe_ctx->stream_res.stream_enc->id,
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
index 3e6c7be7e278..5302d2c9c760 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
@@ -165,7 +165,12 @@ static void set_hpo_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *lin
link_res->hpo_dp_link_enc->funcs->set_link_test_pattern(
link_res->hpo_dp_link_enc, tp_params);
}
+
link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
+
+ // Give retimer extra time to lock before updating DP_TRAINING_PATTERN_SET to TPS1
+ if (tp_params->dp_phy_pattern == DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE)
+ msleep(30);
}
static void set_hpo_fixed_vs_pe_retimer_dp_lane_settings(struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index 0d523dc43d02..bba644024780 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -65,7 +65,7 @@
static const u8 DP_SINK_BRANCH_DEV_NAME_7580[] = "7580\x80u";
-static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
+static const u8 dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
static enum ddc_transaction_type get_ddc_transaction_type(enum signal_type sink_signal)
{
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index b53ad18dbfbc..a9ddbe12142f 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -820,14 +820,14 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
if (should_use_dto_dscclk)
- dccg->funcs->set_dto_dscclk(dccg, dsc->inst);
+ dccg->funcs->set_dto_dscclk(dccg, dsc->inst, true);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
if (should_use_dto_dscclk)
- dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst);
+ dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst, true);
}
dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
dsc_cfg.pic_width *= opp_cnt;
@@ -838,10 +838,11 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
if (dc_is_dp_signal(stream->signal) && !dp_is_128b_132b_signal(pipe_ctx)) {
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);
- pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
- optc_dsc_mode,
- dsc_optc_cfg.bytes_per_pixel,
- dsc_optc_cfg.slice_width);
+ if (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,
+ optc_dsc_mode,
+ dsc_optc_cfg.bytes_per_pixel,
+ dsc_optc_cfg.slice_width);
/* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */
}
@@ -868,19 +869,26 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
NULL,
true);
else {
- pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
- pipe_ctx->stream_res.stream_enc,
- OPTC_DSC_DISABLED, 0, 0);
+ if (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,
+ OPTC_DSC_DISABLED, 0, 0);
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.stream_enc, false, NULL, true);
}
}
/* disable DSC block */
+ if (dccg->funcs->set_dto_dscclk)
+ dccg->funcs->set_dto_dscclk(dccg, pipe_ctx->stream_res.dsc->inst, false);
+ pipe_ctx->stream_res.dsc->funcs->dsc_disconnect(pipe_ctx->stream_res.dsc);
if (dccg->funcs->set_ref_dscclk)
dccg->funcs->set_ref_dscclk(dccg, pipe_ctx->stream_res.dsc->inst);
pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ if (dccg->funcs->set_dto_dscclk)
+ dccg->funcs->set_dto_dscclk(dccg, odm_pipe->stream_res.dsc->inst, false);
+ odm_pipe->stream_res.dsc->funcs->dsc_disconnect(odm_pipe->stream_res.dsc);
if (dccg->funcs->set_ref_dscclk)
dccg->funcs->set_ref_dscclk(dccg, odm_pipe->stream_res.dsc->inst);
odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
@@ -1158,12 +1166,13 @@ static bool poll_for_allocation_change_trigger(struct dc_link *link)
int i;
const int act_retries = 30;
enum act_return_status result = ACT_FAILED;
+ enum dc_connection_type display_connected = (link->type != dc_connection_none);
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;
DC_LOGGER_INIT(link->ctx->logger);
- if (link->aux_access_disabled)
+ if (!display_connected || link->aux_access_disabled)
return true;
for (i = 0; i < act_retries; i++) {
get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);
@@ -1512,6 +1521,7 @@ static bool write_128b_132b_sst_payload_allocation_table(
union payload_table_update_status update_status = { 0 };
const uint32_t max_retries = 30;
uint32_t retries = 0;
+ enum dc_connection_type display_connected = (link->type != dc_connection_none);
DC_LOGGER_INIT(link->ctx->logger);
if (allocate) {
@@ -1529,7 +1539,7 @@ static bool write_128b_132b_sst_payload_allocation_table(
proposed_table->stream_allocations[0].slot_count = req_slot_count;
proposed_table->stream_allocations[0].vcp_id = vc_id;
- if (link->aux_access_disabled)
+ if (!display_connected || link->aux_access_disabled)
return true;
/// Write DPCD 2C0 = 1 to start updating
@@ -1897,7 +1907,9 @@ static void disable_link(struct dc_link *link,
{
if (dc_is_dp_signal(signal)) {
disable_link_dp(link, link_res, signal);
- } else if (signal != SIGNAL_TYPE_VIRTUAL) {
+ } else if (signal == SIGNAL_TYPE_VIRTUAL) {
+ link->dc->hwss.disable_link_output(link, link_res, SIGNAL_TYPE_DISPLAY_PORT);
+ } else {
link->dc->hwss.disable_link_output(link, link_res, signal);
}
@@ -2144,6 +2156,18 @@ static enum dc_status enable_link_dp_mst(
return enable_link_dp(state, pipe_ctx);
}
+static enum dc_status enable_link_virtual(struct pipe_ctx *pipe_ctx)
+{
+ struct dc_link *link = pipe_ctx->stream->link;
+
+ link->dc->hwss.enable_dp_link_output(link,
+ &pipe_ctx->link_res,
+ SIGNAL_TYPE_DISPLAY_PORT,
+ pipe_ctx->clock_source->id,
+ &pipe_ctx->link_config.dp_link_settings);
+ return DC_OK;
+}
+
static enum dc_status enable_link(
struct dc_state *state,
struct pipe_ctx *pipe_ctx)
@@ -2183,7 +2207,7 @@ static enum dc_status enable_link(
status = DC_OK;
break;
case SIGNAL_TYPE_VIRTUAL:
- status = DC_OK;
+ status = enable_link_virtual(pipe_ctx);
break;
default:
break;
@@ -2313,8 +2337,6 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
dc->hwss.disable_audio_stream(pipe_ctx);
- edp_set_panel_assr(link, pipe_ctx, &panel_mode_dp, false);
-
update_psp_stream_config(pipe_ctx, true);
dc->hwss.blank_stream(pipe_ctx);
@@ -2368,6 +2390,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
dc->hwss.disable_stream(pipe_ctx);
disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
}
+ edp_set_panel_assr(link, pipe_ctx, &panel_mode_dp, false);
if (pipe_ctx->stream->timing.flags.DSC) {
if (dc_is_dp_signal(pipe_ctx->stream->signal))
@@ -2428,17 +2451,10 @@ void link_set_dpms_on(
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)
&& !dp_is_128b_132b_signal(pipe_ctx)) {
- struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
-
if (link_enc)
link_enc->funcs->setup(
link_enc,
pipe_ctx->stream->signal);
-
- if (stream_enc && stream_enc->funcs->dig_stream_enable)
- stream_enc->funcs->dig_stream_enable(
- stream_enc,
- pipe_ctx->stream->signal, 1);
}
pipe_ctx->stream->link->link_state_valid = true;
@@ -2538,18 +2554,12 @@ void link_set_dpms_on(
*/
if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||
dp_is_128b_132b_signal(pipe_ctx))) {
- struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
if (link_enc)
link_enc->funcs->setup(
link_enc,
pipe_ctx->stream->signal);
- if (stream_enc && stream_enc->funcs->dig_stream_enable)
- stream_enc->funcs->dig_stream_enable(
- stream_enc,
- pipe_ctx->stream->signal, 1);
-
}
dc->hwss.enable_stream(pipe_ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index cf22b8f28ba6..8073fdae9cb1 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -390,7 +390,7 @@ static void link_destruct(struct dc_link *link)
* the dynamic assignment of link encoders to streams. Virtual links
* are not assigned encoder resources on creation.
*/
- if (link->link_id.id != CONNECTOR_ID_VIRTUAL) {
+ if (link->link_id.id != CONNECTOR_ID_VIRTUAL && link->eng_id != ENGINE_ID_UNKNOWN) {
link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL;
link->dc->res_pool->dig_link_enc_count--;
}
@@ -456,7 +456,6 @@ static bool construct_phy(struct dc_link *link,
struct dc_context *dc_ctx = init_params->ctx;
struct encoder_init_data enc_init_data = { 0 };
struct panel_cntl_init_data panel_cntl_init_data = { 0 };
- struct integrated_info info = { 0 };
struct dc_bios *bios = init_params->dc->ctx->dc_bios;
const struct dc_vbios_funcs *bp_funcs = bios->funcs;
struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 };
@@ -671,42 +670,44 @@ static bool construct_phy(struct dc_link *link,
break;
}
- if (bios->integrated_info)
- info = *bios->integrated_info;
+ if (bios->integrated_info) {
+ /* Look for channel mapping corresponding to connector and device tag */
+ for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
+ struct external_display_path *path =
+ &bios->integrated_info->ext_disp_conn_info.path[i];
- /* Look for channel mapping corresponding to connector and device tag */
- for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
- struct external_display_path *path =
- &info.ext_disp_conn_info.path[i];
+ if (path->device_connector_id.enum_id == link->link_id.enum_id &&
+ path->device_connector_id.id == link->link_id.id &&
+ path->device_connector_id.type == link->link_id.type) {
+ if (link->device_tag.acpi_device != 0 &&
+ path->device_acpi_enum == link->device_tag.acpi_device) {
+ link->ddi_channel_mapping = path->channel_mapping;
+ link->chip_caps = path->caps;
+ DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",
+ link->ddi_channel_mapping.raw);
+ DC_LOG_DC("BIOS object table - chip_caps: %d",
+ link->chip_caps);
+ } else if (path->device_tag ==
+ link->device_tag.dev_id.raw_device_tag) {
+ link->ddi_channel_mapping = path->channel_mapping;
+ link->chip_caps = path->caps;
+ DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X",
+ link->ddi_channel_mapping.raw);
+ DC_LOG_DC("BIOS object table - chip_caps: %d",
+ link->chip_caps);
+ }
- if (path->device_connector_id.enum_id == link->link_id.enum_id &&
- path->device_connector_id.id == link->link_id.id &&
- path->device_connector_id.type == link->link_id.type) {
- if (link->device_tag.acpi_device != 0 &&
- path->device_acpi_enum == link->device_tag.acpi_device) {
- link->ddi_channel_mapping = path->channel_mapping;
- link->chip_caps = path->caps;
- DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw);
- DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps);
- } else if (path->device_tag ==
- link->device_tag.dev_id.raw_device_tag) {
- link->ddi_channel_mapping = path->channel_mapping;
- link->chip_caps = path->caps;
- DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw);
- DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps);
- }
+ if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
+ link->bios_forced_drive_settings.VOLTAGE_SWING =
+ (bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing & 0x3);
+ link->bios_forced_drive_settings.PRE_EMPHASIS =
+ ((bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
+ }
- if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
- link->bios_forced_drive_settings.VOLTAGE_SWING =
- (info.ext_disp_conn_info.fixdpvoltageswing & 0x3);
- link->bios_forced_drive_settings.PRE_EMPHASIS =
- ((info.ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
+ break;
}
-
- break;
}
}
-
if (bios->funcs->get_atom_dc_golden_table)
bios->funcs->get_atom_dc_golden_table(bios);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
index c2d40979203e..d6d5bbf2108c 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
@@ -51,10 +51,6 @@ struct i2c_payloads {
struct vector payloads;
};
-struct aux_payloads {
- struct vector payloads;
-};
-
static bool i2c_payloads_create(
struct dc_context *ctx,
struct i2c_payloads *payloads,
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index a01d0842bf8e..964abccebdc6 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -209,6 +209,9 @@ static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in
case 8100000:
link_rate = LINK_RATE_HIGH3; // Rate_9 (HBR3)- 8.10 Gbps/Lane
break;
+ case 10000000:
+ link_rate = LINK_RATE_UHBR10; // UHBR10 - 10.0 Gbps/Lane
+ break;
default:
link_rate = LINK_RATE_UNKNOWN;
break;
@@ -534,7 +537,7 @@ static bool decide_fallback_link_setting_max_bw_policy(
struct dc_link_settings *cur,
enum link_training_result training_result)
{
- uint8_t cur_idx = 0, next_idx;
+ uint32_t cur_idx = 0, next_idx;
bool found = false;
if (training_result == LINK_TRAINING_ABORT)
@@ -952,6 +955,9 @@ bool link_decide_link_settings(struct dc_stream_state *stream,
} else {
edp_decide_link_settings(link, link_setting, req_bw);
}
+ } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) {
+ link_setting->lane_count = LANE_COUNT_FOUR;
+ link_setting->link_rate = LINK_RATE_HIGH3;
} else {
decide_dp_link_settings(link, link_setting, req_bw);
}
@@ -2059,7 +2065,7 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
enum dc_link_rate lttpr_max_link_rate;
enum dc_link_rate cable_max_link_rate;
struct link_encoder *link_enc = NULL;
-
+ bool is_uhbr13_5_supported = true;
link_enc = link_enc_cfg_get_link_enc(link);
ASSERT(link_enc);
@@ -2080,6 +2086,9 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
max_link_cap.link_spread =
link->reported_link_cap.link_spread;
+ if (!link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5)
+ is_uhbr13_5_supported = false;
+
/* Lower link settings based on cable attributes
* Cable ID is a DP2 feature to identify max certified link rate that
* a cable can carry. The cable identification method requires both
@@ -2098,9 +2107,13 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
cable_max_link_rate = get_cable_max_link_rate(link);
if (!link->dc->debug.ignore_cable_id &&
- cable_max_link_rate != LINK_RATE_UNKNOWN &&
- cable_max_link_rate < max_link_cap.link_rate)
- max_link_cap.link_rate = cable_max_link_rate;
+ cable_max_link_rate != LINK_RATE_UNKNOWN) {
+ if (cable_max_link_rate < max_link_cap.link_rate)
+ max_link_cap.link_rate = cable_max_link_rate;
+
+ if (!link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY)
+ is_uhbr13_5_supported = false;
+ }
/* account for lttpr repeaters cap
* notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
@@ -2113,12 +2126,19 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
if (lttpr_max_link_rate < max_link_cap.link_rate)
max_link_cap.link_rate = lttpr_max_link_rate;
+ if (!link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5)
+ is_uhbr13_5_supported = false;
+
DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
__func__,
max_link_cap.lane_count,
max_link_cap.link_rate);
}
+ if (max_link_cap.link_rate == LINK_RATE_UHBR13_5 &&
+ !is_uhbr13_5_supported)
+ max_link_cap.link_rate = LINK_RATE_UHBR10;
+
if (link_dp_get_encoding_format(&max_link_cap) == DP_128b_132b_ENCODING &&
link->dc->debug.disable_uhbr)
max_link_cap.link_rate = LINK_RATE_HIGH3;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
index 0fcf0b8530ac..5f087e930cb6 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
@@ -189,16 +189,30 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link)
union dpcd_replay_configuration replay_configuration = {0};
/*AMD Replay version reuse DP_PSR_ERROR_STATUS for REPLAY_ERROR status.*/
union psr_error_status replay_error_status = {0};
+ bool ret = false;
+ int retries = 0;
if (!link->replay_settings.replay_feature_enabled)
return;
- dm_helpers_dp_read_dpcd(
- link->ctx,
- link,
- DP_SINK_PR_REPLAY_STATUS,
- &replay_configuration.raw,
- sizeof(replay_configuration.raw));
+ while (retries < 10) {
+ ret = dm_helpers_dp_read_dpcd(
+ link->ctx,
+ link,
+ DP_SINK_PR_REPLAY_STATUS,
+ &replay_configuration.raw,
+ sizeof(replay_configuration.raw));
+
+ if (ret)
+ break;
+
+ retries++;
+ }
+
+ if (!ret)
+ DC_LOG_WARNING("[%s][%d] DPCD read addr.0x%x failed with %d retries\n",
+ __func__, __LINE__,
+ DP_SINK_PR_REPLAY_STATUS, retries);
dm_helpers_dp_read_dpcd(
link->ctx,
@@ -373,6 +387,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
union device_service_irq device_service_clear = {0};
enum dc_status result;
bool status = false;
+ bool allow_active = false;
if (out_link_loss)
*out_link_loss = false;
@@ -427,12 +442,6 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
return false;
}
- if (handle_hpd_irq_psr_sink(link))
- /* PSR-related error was detected and handled */
- return true;
-
- handle_hpd_irq_replay_sink(link);
-
/* If PSR-related error handled, Main link may be off,
* so do not handle as a normal sink status change interrupt.
*/
@@ -454,9 +463,8 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
* If we got sink count changed it means
* Downstream port status changed,
* then DM should call DC to do the detection.
- * NOTE: Do not handle link loss on eDP since it is internal link*/
- if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
- dp_parse_link_loss_status(
+ */
+ if (dp_parse_link_loss_status(
link,
&hpd_irq_dpcd_data)) {
/* Connectivity log: link loss */
@@ -465,6 +473,11 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
sizeof(hpd_irq_dpcd_data),
"Status: ");
+ if (link->psr_settings.psr_feature_enabled)
+ edp_set_psr_allow_active(link, &allow_active, true, false, NULL);
+ else if (link->replay_settings.replay_allow_active)
+ edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
+
if (defer_handling && has_left_work)
*has_left_work = true;
else
@@ -477,6 +490,14 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
dp_trace_link_loss_increment(link);
}
+ if (*out_link_loss == false) {
+ if (handle_hpd_irq_psr_sink(link))
+ /* PSR-related error was detected and handled */
+ return true;
+
+ handle_hpd_irq_replay_sink(link);
+ }
+
if (link->type == dc_connection_sst_branch &&
hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
!= link->dpcd_sink_count)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
index 2fa4e64e2430..bafa52a0165a 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
@@ -147,32 +147,25 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource
link_enc = link_enc_cfg_get_link_enc(link);
ASSERT(link_enc);
+ if (link_enc->funcs->fec_set_ready == NULL)
+ return DC_NOT_SUPPORTED;
- if (!dp_should_enable_fec(link))
- return status;
+ if (ready && dp_should_enable_fec(link)) {
+ fec_config = 1;
- if (link_enc->funcs->fec_set_ready &&
- link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
- if (ready) {
- fec_config = 1;
- status = core_link_write_dpcd(link,
- DP_FEC_CONFIGURATION,
- &fec_config,
- sizeof(fec_config));
- if (status == DC_OK) {
- link_enc->funcs->fec_set_ready(link_enc, true);
- link->fec_state = dc_link_fec_ready;
- } else {
- link_enc->funcs->fec_set_ready(link_enc, false);
- link->fec_state = dc_link_fec_not_ready;
- dm_error("dpcd write failed to set fec_ready");
- }
- } else if (link->fec_state == dc_link_fec_ready) {
+ status = core_link_write_dpcd(link, DP_FEC_CONFIGURATION,
+ &fec_config, sizeof(fec_config));
+
+ if (status == DC_OK) {
+ link_enc->funcs->fec_set_ready(link_enc, true);
+ link->fec_state = dc_link_fec_ready;
+ }
+ } else {
+ if (link->fec_state == dc_link_fec_ready) {
fec_config = 0;
- status = core_link_write_dpcd(link,
- DP_FEC_CONFIGURATION,
- &fec_config,
- sizeof(fec_config));
+ core_link_write_dpcd(link, DP_FEC_CONFIGURATION,
+ &fec_config, sizeof(fec_config));
+
link_enc->funcs->fec_set_ready(link_enc, false);
link->fec_state = dc_link_fec_not_ready;
}
@@ -187,14 +180,12 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
link_enc = link_enc_cfg_get_link_enc(link);
ASSERT(link_enc);
-
- if (!dp_should_enable_fec(link))
+ if (link_enc->funcs->fec_set_enable == NULL)
return;
- if (link_enc->funcs->fec_set_enable &&
- link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
- if (link->fec_state == dc_link_fec_ready && enable) {
- /* Accord to DP spec, FEC enable sequence can first
+ if (enable && dp_should_enable_fec(link)) {
+ if (link->fec_state == dc_link_fec_ready) {
+ /* According to DP spec, FEC enable sequence can first
* be transmitted anytime after 1000 LL codes have
* been transmitted on the link after link training
* completion. Using 1 lane RBR should have the maximum
@@ -204,7 +195,9 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
udelay(7);
link_enc->funcs->fec_set_enable(link_enc, true);
link->fec_state = dc_link_fec_enabled;
- } else if (link->fec_state == dc_link_fec_enabled && !enable) {
+ }
+ } else {
+ if (link->fec_state == dc_link_fec_enabled) {
link_enc->funcs->fec_set_enable(link_enc, false);
link->fec_state = dc_link_fec_ready;
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
index 1818970b8eaf..a93dd83cd8c0 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
@@ -914,10 +914,10 @@ static enum dc_status configure_lttpr_mode_non_transparent(
/* Driver does not need to train the first hop. Skip DPCD read and clear
* AUX_RD_INTERVAL for DPTX-to-DPIA hop.
*/
- if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
+ if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && repeater_cnt > 0 && repeater_cnt < MAX_REPEATER_CNT)
link->dpcd_caps.lttpr_caps.aux_rd_interval[--repeater_cnt] = 0;
- for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
+ for (repeater_id = repeater_cnt; repeater_id > 0 && repeater_id < MAX_REPEATER_CNT; repeater_id--) {
aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
core_link_read_dpcd(
@@ -1704,10 +1704,13 @@ bool perform_link_training_with_retries(
is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
(cur_link_settings.lane_count <= LANE_COUNT_ONE));
- if (is_link_bw_low)
+ if (is_link_bw_low) {
DC_LOG_WARNING(
"%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n",
__func__, link->link_index, req_bw, link_bw);
+
+ return false;
+ }
}
msleep(delay_between_attempts);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
index edb21d21952a..cd1975c03f38 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
@@ -430,10 +430,6 @@ static enum link_training_result dpia_training_cr_non_transparent(
retry_count++;
}
- /* Abort link training if clock recovery failed due to HPD unplug. */
- if (link->is_hpd_pending)
- result = LINK_TRAINING_ABORT;
-
DC_LOG_HW_LINK_TRAINING(
"%s\n DPIA(%d) clock recovery\n -hop(%d)\n - result(%d)\n - retries(%d)\n - status(%d)\n",
__func__,
@@ -537,10 +533,6 @@ static enum link_training_result dpia_training_cr_transparent(
retry_count++;
}
- /* Abort link training if clock recovery failed due to HPD unplug. */
- if (link->is_hpd_pending)
- result = LINK_TRAINING_ABORT;
-
DC_LOG_HW_LINK_TRAINING("%s\n DPIA(%d) clock recovery\n -hop(%d)\n - result(%d)\n - retries(%d)\n",
__func__,
link->link_id.enum_id - ENUM_ID_1,
@@ -731,10 +723,6 @@ static enum link_training_result dpia_training_eq_non_transparent(
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
}
- /* Abort link training if equalization failed due to HPD unplug. */
- if (link->is_hpd_pending)
- result = LINK_TRAINING_ABORT;
-
DC_LOG_HW_LINK_TRAINING(
"%s\n DPIA(%d) equalization\n - hop(%d)\n - result(%d)\n - retries(%d)\n - status(%d)\n",
__func__,
@@ -822,10 +810,6 @@ static enum link_training_result dpia_training_eq_transparent(
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
}
- /* Abort link training if equalization failed due to HPD unplug. */
- if (link->is_hpd_pending)
- result = LINK_TRAINING_ABORT;
-
DC_LOG_HW_LINK_TRAINING("%s\n DPIA(%d) equalization\n - hop(%d)\n - result(%d)\n - retries(%d)\n",
__func__,
link->link_id.enum_id - ENUM_ID_1,
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
index a72c898b64fa..584b9295a12a 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
@@ -165,6 +165,7 @@ static void dpcd_extend_address_range(
*out_address = new_addr_range.start;
*out_size = ADDRESS_RANGE_SIZE(new_addr_range.start, new_addr_range.end);
*out_data = kcalloc(*out_size, sizeof(**out_data), GFP_KERNEL);
+ ASSERT(*out_data);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
index ad9aca790dd7..89f66d88c3b0 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
@@ -248,6 +248,9 @@ bool edp_backlight_enable_aux(struct dc_link *link, bool enable)
link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
return false;
+ if (link->dc->debug.edp_oled_no_backlight_enable && link->dpcd_sink_ext_caps.bits.oled)
+ return true;
+
if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
&backlight_enable, 1) != DC_OK)
return false;