diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/link')
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; |
