drm/amd/display: USB4 DPIA enumeration and AUX Tunneling
authorMeenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Tue, 26 Jan 2021 20:15:33 +0000 (15:15 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 6 Oct 2021 19:50:56 +0000 (15:50 -0400)
[WHY]
To enable dc links for USB4 DPIA ports and AUX command tunneling
for YELLOW_CARP_B0.

[HOW]
1) Created dc links for all USB4 DPIA ports in create_links().
   dc_link_construct() implementation is split for legacy DDC and DPIAs.
   As usb4 has no ddc, ddc->ddc_pin will be set to NULL for its dc link
   and this parameter will be used to identify the dc links as DPIA. The
   dc link for DPIA is further to be enhanced with implementation for link
   encoder and link initialization.
2) usb4_dpia_count in struct resource_pool will be initialized to 4 in
   dcn31_resource_construct() if the DCN is YELLOW_CARP_B0.
3) Enabled DMUB AUX via outbox for YELLOW_CARP_B0.

Reviewed-by: Jimmy Kizito <Jimmy.Kizito@amd.com>
Acked-by: Wayne Lin <Wayne.Lin@amd.com>
Acked-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Meenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
drivers/gpu/drm/amd/display/dc/irq_types.h

index e762fce103fb73151f55241c7dd01638f7350300..1a523f3e071b549c551c350a5519831cfd6794f4 100644 (file)
@@ -231,6 +231,25 @@ static bool create_links(
 
        DC_LOG_DC("BIOS object table - end");
 
+       /* Create a link for each usb4 dpia port */
+       for (i = 0; i < dc->res_pool->usb4_dpia_count; i++) {
+               struct link_init_data link_init_params = {0};
+               struct dc_link *link;
+
+               link_init_params.ctx = dc->ctx;
+               link_init_params.connector_index = i;
+               link_init_params.link_index = dc->link_count;
+               link_init_params.dc = dc;
+               link_init_params.is_dpia_link = true;
+
+               link = link_create(&link_init_params);
+               if (link) {
+                       dc->links[dc->link_count] = link;
+                       link->dc = dc;
+                       ++dc->link_count;
+               }
+       }
+
        for (i = 0; i < num_virtual_links; i++) {
                struct dc_link *link = kzalloc(sizeof(*link), GFP_KERNEL);
                struct encoder_init_data enc_init = {0};
@@ -3557,6 +3576,12 @@ void dc_hardware_release(struct dc *dc)
  */
 bool dc_enable_dmub_notifications(struct dc *dc)
 {
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       /* YELLOW_CARP B0 USB4 DPIA needs dmub notifications for interrupts */
+       if (dc->ctx->asic_id.chip_family == FAMILY_YELLOW_CARP &&
+           dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0)
+               return true;
+#endif
        /* dmub aux needs dmub notifications to be enabled */
        return dc->debug.enable_dmub_aux_for_legacy_ddc;
 }
@@ -3582,7 +3607,12 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
 
        cmd.dp_aux_access.header.type = DMUB_CMD__DP_AUX_ACCESS;
        cmd.dp_aux_access.header.payload_bytes = 0;
-       cmd.dp_aux_access.aux_control.type = AUX_CHANNEL_LEGACY_DDC;
+       /* For dpia, ddc_pin is set to NULL */
+       if (!dc->links[link_index]->ddc->ddc_pin)
+               cmd.dp_aux_access.aux_control.type = AUX_CHANNEL_DPIA;
+       else
+               cmd.dp_aux_access.aux_control.type = AUX_CHANNEL_LEGACY_DDC;
+
        cmd.dp_aux_access.aux_control.instance = dc->links[link_index]->ddc_hw_inst;
        cmd.dp_aux_access.aux_control.sw_crc_enabled = 0;
        cmd.dp_aux_access.aux_control.timeout = 0;
index 64b9c493dce2578557d48093a98c4d68372501a7..20b4819b73e411c9cae0bc1eca1917d18e73d56e 100644 (file)
@@ -1425,8 +1425,8 @@ static enum transmitter translate_encoder_to_transmitter(struct graphics_object_
        }
 }
 
-static bool dc_link_construct(struct dc_link *link,
-                             const struct link_init_data *init_params)
+static bool dc_link_construct_legacy(struct dc_link *link,
+                                    const struct link_init_data *init_params)
 {
        uint8_t i;
        struct ddc_service_init_data ddc_service_init_data = { { 0 } };
@@ -1701,6 +1701,73 @@ create_fail:
        return false;
 }
 
+static bool dc_link_construct_dpia(struct dc_link *link,
+                                  const struct link_init_data *init_params)
+{
+       struct ddc_service_init_data ddc_service_init_data = { { 0 } };
+       struct dc_context *dc_ctx = init_params->ctx;
+
+       DC_LOGGER_INIT(dc_ctx->logger);
+
+       /* Initialized dummy hpd and hpd rx */
+       link->irq_source_hpd = DC_IRQ_SOURCE_USB4_DMUB_HPD;
+       link->irq_source_hpd_rx = DC_IRQ_SOURCE_USB4_DMUB_HPDRX;
+       link->link_status.dpcd_caps = &link->dpcd_caps;
+
+       link->dc = init_params->dc;
+       link->ctx = dc_ctx;
+       link->link_index = init_params->link_index;
+
+       memset(&link->preferred_training_settings, 0,
+              sizeof(struct dc_link_training_overrides));
+       memset(&link->preferred_link_setting, 0,
+              sizeof(struct dc_link_settings));
+
+       /* Dummy Init for linkid */
+       link->link_id.type = OBJECT_TYPE_CONNECTOR;
+       link->link_id.id = CONNECTOR_ID_DISPLAY_PORT;
+       link->is_internal_display = false;
+       link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
+       LINK_INFO("Connector[%d] description:signal %d\n",
+                 init_params->connector_index,
+                 link->connector_signal);
+
+       /* TODO: Initialize link : funcs->link_init */
+
+       ddc_service_init_data.ctx = link->ctx;
+       ddc_service_init_data.id = link->link_id;
+       ddc_service_init_data.link = link;
+       /* Set indicator for dpia link so that ddc won't be created */
+       ddc_service_init_data.is_dpia_link = true;
+
+       link->ddc = dal_ddc_service_create(&ddc_service_init_data);
+       if (!link->ddc) {
+               DC_ERROR("Failed to create ddc_service!\n");
+               goto ddc_create_fail;
+       }
+
+       /* Set dpia port index : 0 to number of dpia ports */
+       link->ddc_hw_inst = init_params->connector_index;
+
+       /* TODO: Create link encoder */
+
+       link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
+
+       return true;
+
+ddc_create_fail:
+       return false;
+}
+
+static bool dc_link_construct(struct dc_link *link,
+                             const struct link_init_data *init_params)
+{
+       /* Handle dpia case */
+       if (init_params->is_dpia_link)
+               return dc_link_construct_dpia(link, init_params);
+       else
+               return dc_link_construct_legacy(link, init_params);
+}
 /*******************************************************************************
  * Public functions
  ******************************************************************************/
index ba6b56f2026907438494d9eec23d4f164f1776aa..dd6c473be072eff2bde16a8864f1361982709f5d 100644 (file)
@@ -196,7 +196,8 @@ static void ddc_service_construct(
        ddc_service->link = init_data->link;
        ddc_service->ctx = init_data->ctx;
 
-       if (BP_RESULT_OK != dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info)) {
+       if (init_data->is_dpia_link ||
+           dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info) != BP_RESULT_OK) {
                ddc_service->ddc_pin = NULL;
        } else {
                DC_LOGGER_INIT(ddc_service->ctx->logger);
index 80f06ceccea8b96c6eebb6b3435f6ac9ba9262a5..18e33ef3d21760225ecc2ad1e6cae786049c8e73 100644 (file)
@@ -174,6 +174,10 @@ void dcn31_init_hw(struct dc *dc)
                if (hws->funcs.dsc_pg_control != NULL)
                        hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
 
+       /* Enables outbox notifications for usb4 dpia */
+       if (dc->res_pool->usb4_dpia_count)
+               dmub_enable_outbox_notification(dc);
+
        /* we want to turn off all dp displays before doing detection */
        if (dc->config.power_down_display_on_boot)
                blank_all_dp_displays(dc, true);
@@ -278,8 +282,10 @@ void dcn31_init_hw(struct dc *dc)
        if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
                dc->res_pool->hubbub->funcs->force_pstate_change_control(
                                dc->res_pool->hubbub, false, false);
+#if defined(CONFIG_DRM_AMD_DC_DCN)
        if (dc->res_pool->hubbub->funcs->init_crb)
                dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
+#endif
 }
 
 void dcn31_dsc_pg_control(
index d5b58025f0cc5c3e544b293310e3db67a944b76a..2e021f9345c0c8af79c82a0dcda6f2204465cb04 100644 (file)
@@ -2427,6 +2427,12 @@ static bool dcn31_resource_construct(
                pool->base.sw_i2cs[i] = NULL;
        }
 
+       if (dc->ctx->asic_id.chip_family == FAMILY_YELLOW_CARP &&
+           dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
+               /* YELLOW CARP B0 has 4 DPIA's */
+               pool->base.usb4_dpia_count = 4;
+       }
+
        /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */
        if (!resource_construct(num_virtual_links, dc, &pool->base,
                        (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
index ed09af2389110cfc8f87eb03bba0b9bfa6fe3a61..6fc6488c54c08467c9609d47b35f21fdb3998c7a 100644 (file)
@@ -62,6 +62,7 @@ struct link_init_data {
        uint32_t connector_index; /* this will be mapped to the HPD pins */
        uint32_t link_index; /* this is mapped to DAL display_index
                                TODO: remove it when DC is complete. */
+       bool is_dpia_link;
 };
 
 struct dc_link *link_create(const struct link_init_data *init_params);
index 4d7b271b64097ccaf1d184bf0fc2f583a120a1dd..95fb61d62778aa014ec1046c12f94dcefb1b8eba 100644 (file)
@@ -69,6 +69,7 @@ struct ddc_service_init_data {
        struct graphics_object_id id;
        struct dc_context *ctx;
        struct dc_link *link;
+       bool is_dpia_link;
 };
 
 struct ddc_service *dal_ddc_service_create(
index 530c2578db406d68e7db326c6dc053b21ba49eb0..7a9f667d5edb465968af130b370186ba54cea7e1 100644 (file)
@@ -153,7 +153,10 @@ enum dc_irq_source {
        DC_IRQ_SOURCE_DMCUB_OUTBOX,
        DC_IRQ_SOURCE_DMCUB_OUTBOX0,
        DC_IRQ_SOURCE_DMCUB_GENERAL_DATAOUT,
-       DAL_IRQ_SOURCES_NUMBER
+       DAL_IRQ_SOURCES_NUMBER,
+       /* Dummy interrupt source for USB4 HPD & HPD RX */
+       DC_IRQ_SOURCE_USB4_DMUB_HPD,
+       DC_IRQ_SOURCE_USB4_DMUB_HPDRX,
 };
 
 enum irq_type