diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc_link.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link.c | 104 |
1 files changed, 76 insertions, 28 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f4a2088ab179..fa5059f71727 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -203,9 +203,21 @@ static bool program_hpd_filter(const struct dc_link *link) return result; } +bool dc_link_wait_for_t12(struct dc_link *link) +{ + if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) { + link->dc->hwss.edp_wait_for_T12(link); + + return true; + } + + return false; +} + /** * dc_link_detect_sink() - Determine if there is a sink connected * + * @link: pointer to the dc link * @type: Returned connection type * Does not detect downstream devices, such as MST sinks * or display connected through active dongles @@ -342,7 +354,7 @@ static enum signal_type get_basic_signal_type(struct graphics_object_id encoder, return SIGNAL_TYPE_NONE; } -/** +/* * dc_link_is_dp_sink_present() - Check if there is a native DP * or passive DP-HDMI dongle connected */ @@ -596,8 +608,6 @@ static void query_hdcp_capability(enum signal_type signal, struct dc_link *link) dc_process_hdcp_msg(signal, link, &msg22); if (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - enum hdcp_message_status status = HDCP_MESSAGE_UNSUPPORTED; - msg14.data = &link->hdcp_caps.bcaps.raw; msg14.length = sizeof(link->hdcp_caps.bcaps.raw); msg14.msg_id = HDCP_MESSAGE_ID_READ_BCAPS; @@ -605,7 +615,7 @@ static void query_hdcp_capability(enum signal_type signal, struct dc_link *link) msg14.link = HDCP_LINK_PRIMARY; msg14.max_retries = 5; - status = dc_process_hdcp_msg(signal, link, &msg14); + dc_process_hdcp_msg(signal, link, &msg14); } } @@ -830,7 +840,7 @@ static bool wait_for_entering_dp_alt_mode(struct dc_link *link) return false; } -/** +/* * dc_link_detect() - Detect if a sink is attached to a given link * * link->local_sink is created or destroyed as needed. @@ -1065,9 +1075,6 @@ static bool dc_link_detect_helper(struct dc_link *link, break; } - if (link->local_sink->edid_caps.panel_patch.disable_fec) - link->ctx->dc->debug.disable_fec = true; - // Check if edid is the same if ((prev_sink) && (edid_status == EDID_THE_SAME || edid_status == EDID_OK)) @@ -1366,13 +1373,17 @@ static bool dc_link_construct(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 integrated_info *info; 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 }; DC_LOGGER_INIT(dc_ctx->logger); + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto create_fail; + link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; @@ -1390,10 +1401,12 @@ static bool dc_link_construct(struct dc_link *link, link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); + DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id); if (bios->funcs->get_disp_connector_caps_info) { bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info); link->is_internal_display = disp_connect_caps_info.INTERNAL_DISPLAY; + DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display); } if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { @@ -1408,10 +1421,14 @@ static bool dc_link_construct(struct dc_link *link, link->hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); + if (link->hpd_gpio) { dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT); dal_gpio_unlock_pin(link->hpd_gpio); link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio); + + DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id); + DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en); } switch (link->link_id.id) { @@ -1470,6 +1487,11 @@ static bool dc_link_construct(struct dc_link *link, goto ddc_create_fail; } + if (!link->ddc->ddc_pin) { + DC_ERROR("Failed to get I2C info for connector!\n"); + goto ddc_create_fail; + } + link->ddc_hw_inst = dal_ddc_get_line(dal_ddc_service_get_ddc_pin(link->ddc)); @@ -1508,6 +1530,8 @@ static bool dc_link_construct(struct dc_link *link, goto link_enc_create_fail; } + DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C); + link->link_enc_hw_inst = link->link_enc->transmitter; for (i = 0; i < 4; i++) { @@ -1530,16 +1554,20 @@ static bool dc_link_construct(struct dc_link *link, if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD && link->connector_signal == SIGNAL_TYPE_RGB) continue; + + DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device); + DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type); + DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id); break; } if (bios->integrated_info) - info = *bios->integrated_info; + memcpy(info, bios->integrated_info, sizeof(*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 = - &info.ext_disp_conn_info.path[i]; + &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 && @@ -1548,10 +1576,14 @@ static bool dc_link_construct(struct dc_link *link, 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); } break; } @@ -1570,6 +1602,7 @@ static bool dc_link_construct(struct dc_link *link, link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; + DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__); return true; device_tag_fail: link->link_enc->funcs->destroy(&link->link_enc); @@ -1586,6 +1619,9 @@ create_fail: link->hpd_gpio = NULL; } + DC_LOG_DC("BIOS object table - %s failed.\n", __func__); + kfree(info); + return false; } @@ -3133,17 +3169,17 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) { struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp; if (cp_psp && cp_psp->funcs.update_stream_config) { - struct cp_psp_stream_config config; - - memset(&config, 0, sizeof(config)); + struct cp_psp_stream_config config = {0}; + enum dp_panel_mode panel_mode = + dp_get_panel_mode(pipe_ctx->stream->link); config.otg_inst = (uint8_t) pipe_ctx->stream_res.tg->inst; - /*stream_enc_inst*/ - config.stream_enc_inst = (uint8_t) pipe_ctx->stream_res.stream_enc->stream_enc_inst; - config.link_enc_inst = pipe_ctx->stream->link->link_enc_hw_inst; + config.dig_fe = (uint8_t) pipe_ctx->stream_res.stream_enc->stream_enc_inst; + config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst; config.dpms_off = dpms_off; config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context; - config.mst_supported = (pipe_ctx->stream->signal == + config.assr_enabled = (panel_mode == DP_PANEL_MODE_EDP); + config.mst_enabled = (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST); cp_psp->funcs.update_stream_config(cp_psp->handle, &config); } @@ -3396,10 +3432,7 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) } /** - ***************************************************************************** - * Function: dc_link_enable_hpd_filter - * - * @brief + * dc_link_enable_hpd_filter: * If enable is true, programs HPD filter on associated HPD line using * delay_on_disconnect/delay_on_connect values dependent on * link->connector_signal @@ -3407,9 +3440,8 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) * If enable is false, programs HPD filter on associated HPD line with no * delays on connect or disconnect * - * @param [in] link: pointer to the dc link - * @param [in] enable: boolean specifying whether to enable hbd - ***************************************************************************** + * @link: pointer to the dc link + * @enable: boolean specifying whether to enable hbd */ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable) { @@ -3635,7 +3667,7 @@ uint32_t dc_link_bandwidth_kbps( link_bw_kbps *= 8; /* 8 bits per byte*/ link_bw_kbps *= link_setting->lane_count; - if (dc_link_is_fec_supported(link) && !link->dc->debug.disable_fec) { + if (dc_link_should_enable_fec(link)) { /* Account for FEC overhead. * We have to do it based on caps, * and not based on FEC being set ready, @@ -3656,8 +3688,8 @@ uint32_t dc_link_bandwidth_kbps( * but the difference is minimal and is in a safe direction, * which all works well around potential ambiguity of DP 1.4a spec. */ - link_bw_kbps = mul_u64_u32_shr(BIT_ULL(32) * 970LL / 1000, - link_bw_kbps, 32); + long long fec_link_bw_kbps = link_bw_kbps * 970LL; + link_bw_kbps = (uint32_t)(div64_s64(fec_link_bw_kbps, 1000LL)); } return link_bw_kbps; @@ -3687,3 +3719,19 @@ bool dc_link_is_fec_supported(const struct dc_link *link) !IS_FPGA_MAXIMUS_DC(link->ctx->dce_environment)); } +bool dc_link_should_enable_fec(const struct dc_link *link) +{ + bool is_fec_disable = false; + bool ret = false; + + if ((link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT_MST && + link->local_sink && + link->local_sink->edid_caps.panel_patch.disable_fec) || + link->connector_signal == SIGNAL_TYPE_EDP) // Disable FEC for eDP + is_fec_disable = true; + + if (dc_link_is_fec_supported(link) && !link->dc->debug.disable_fec && !is_fec_disable) + ret = true; + + return ret; +} |