}
}
+static uint8_t get_lowest_dpia_index(const struct dc_link *link)
+{
+ const struct dc *dc_struct = link->dc;
+ uint8_t idx = 0xFF;
+ int i;
+
+ for (i = 0; i < MAX_PIPES * 2; ++i) {
+ if (!dc_struct->links[i] || dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
+ continue;
+
+ if (idx > dc_struct->links[i]->link_index)
+ idx = dc_struct->links[i]->link_index;
+ }
+
+ return idx;
+}
+
+static void dcn35_notify_host_router_bw(struct clk_mgr *clk_mgr_base, struct dc_state *context,
+ bool safe_to_lower)
+{
+ struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ uint32_t host_router_bw_kbps[MAX_HOST_ROUTERS_NUM] = { 0 };
+ int i;
+
+ for (i = 0; i < context->stream_count; ++i) {
+ const struct dc_stream_state *stream = context->streams[i];
+ const struct dc_link *link = stream->link;
+ uint8_t lowest_dpia_index = 0, hr_index = 0;
+
+ if (!link)
+ continue;
+
+ lowest_dpia_index = get_lowest_dpia_index(link);
+ if (link->link_index < lowest_dpia_index)
+ continue;
+
+ hr_index = (link->link_index - lowest_dpia_index) / 2;
+ host_router_bw_kbps[hr_index] += dc_bandwidth_in_kbps_from_timing(
+ &stream->timing, dc_link_get_highest_encoding_format(link));
+ }
+
+ for (i = 0; i < MAX_HOST_ROUTERS_NUM; ++i) {
+ new_clocks->host_router_bw_kbps[i] = host_router_bw_kbps[i];
+ if (should_set_clock(safe_to_lower, new_clocks->host_router_bw_kbps[i], clk_mgr_base->clks.host_router_bw_kbps[i])) {
+ clk_mgr_base->clks.host_router_bw_kbps[i] = new_clocks->host_router_bw_kbps[i];
+ dcn35_smu_notify_host_router_bw(clk_mgr, i, new_clocks->host_router_bw_kbps[i]);
+ }
+ }
+}
+
void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
struct dc_state *context,
bool safe_to_lower)
dcn35_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
}
+ // notify PMFW of bandwidth per DPIA tunnel
+ if (dc->debug.notify_dpia_hr_bw)
+ dcn35_notify_host_router_bw(clk_mgr_base, context, safe_to_lower);
+
// notify DMCUB of latest clocks
memset(&cmd, 0, sizeof(cmd));
cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR;
#define VBIOSSMC_MSG_DisableLSdma 0x1A ///< Disable LSDMA; only sent by VBIOS
#define VBIOSSMC_MSG_DpControllerPhyStatus 0x1B ///< Inform PMFW about the pre conditions for turning SLDO2 on/off . bit[0]==1 precondition is met, bit[1-2] are for DPPHY number
#define VBIOSSMC_MSG_QueryIPS2Support 0x1C ///< Return 1: support; else not supported
-#define VBIOSSMC_Message_Count 0x1D
+#define VBIOSSMC_MSG_NotifyHostRouterBW 0x1D
+#define VBIOSSMC_Message_Count 0x1E
#define VBIOSSMC_Status_BUSY 0x0
#define VBIOSSMC_Result_OK 0x1
#define VBIOSSMC_Result_CmdRejectedPrereq 0xFD
#define VBIOSSMC_Result_CmdRejectedBusy 0xFC
+union dcn35_dpia_host_router_bw {
+ struct {
+ uint32_t hr_id : 16;
+ uint32_t bw_mbps : 16;
+ } bits;
+ uint32_t all;
+};
+
/*
* Function to be used instead of REG_WAIT macro because the wait ends when
* the register is NOT EQUAL to zero, and because `the translation in msg_if.h
//smu_print("%s: VBIOSSMC_MSG_QueryIPS2Support return = %x\n", __func__, retv);
return retv;
}
+
+void dcn35_smu_notify_host_router_bw(struct clk_mgr_internal *clk_mgr, uint32_t hr_id, uint32_t bw_kbps)
+{
+ union dcn35_dpia_host_router_bw msg_data = { 0 };
+
+ msg_data.bits.hr_id = hr_id;
+ msg_data.bits.bw_mbps = bw_kbps / 1000;
+
+ dcn35_smu_send_msg_with_param(clk_mgr, VBIOSSMC_MSG_NotifyHostRouterBW, msg_data.all);
+}
#define MAX_STREAMS 6
#define MIN_VIEWPORT_SIZE 12
#define MAX_NUM_EDP 2
+#define MAX_HOST_ROUTERS_NUM 2
/* Display Core Interfaces */
struct dc_versions {
bool prev_p_state_change_support;
bool fclk_prev_p_state_change_support;
int num_ways;
+ int host_router_bw_kbps[MAX_HOST_ROUTERS_NUM];
/*
* @fw_based_mclk_switching
unsigned int force_easf;
unsigned int force_sharpness;
unsigned int force_lls;
+ bool notify_dpia_hr_bw;
};