@@ -229,6 +229,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};
@@ -3509,6 +3528,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;
}
@@ -3534,7 +3559,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;
@@ -1378,8 +1378,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 } };
@@ -1651,6 +1651,73 @@ static bool dc_link_construct(struct dc_link *link,
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
******************************************************************************/
@@ -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);
@@ -169,6 +169,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) {
uint8_t dpcd_power_state = '\0';
@@ -302,8 +306,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(
@@ -2180,6 +2180,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) ?
@@ -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);
@@ -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(
@@ -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