#include "dcn42_soc_and_ip_translator.h"
#include "../dcn401/dcn401_soc_and_ip_translator.h"
#include "bounding_boxes/dcn42_soc_bb.h"
#include "bounding_boxes/dcn42b_soc_bb.h"
static void get_default_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc)
{
if (dc->ctx->dce_version == DCN_VERSION_4_2B) {
memcpy(soc_bb, &dml2_socbb_dcn42b, sizeof(struct dml2_soc_bb));
memcpy(&soc_bb->qos_parameters, &dml_dcn42b_variant_a_soc_qos_params, sizeof(struct dml2_soc_qos_parameters));
} else {
memcpy(soc_bb, &dml2_socbb_dcn42, sizeof(struct dml2_soc_bb));
memcpy(&soc_bb->qos_parameters, &dml_dcn42_variant_a_soc_qos_params, sizeof(struct dml2_soc_qos_parameters));
}
}
static void dcn42_convert_dc_clock_table_to_soc_bb_clock_table(
struct dml2_soc_state_table *dml_clk_table,
struct dml2_soc_vmin_clock_limits *vmin_limit,
const struct clk_bw_params *dc_bw_params)
{
int i;
const struct clk_limit_table *dc_clk_table;
if (dc_bw_params == NULL)
return;
dc_clk_table = &dc_bw_params->clk_table;
if (dc_clk_table->num_entries_per_clk.num_fclk_levels && dc_clk_table->num_entries_per_clk.num_dcfclk_levels) {
dml_clk_table->fclk.num_clk_values = (uint8_t)dc_clk_table->num_entries_per_clk.num_dcfclk_levels;
dml_clk_table->dcfclk.num_clk_values = (uint8_t)dc_clk_table->num_entries_per_clk.num_dcfclk_levels;
for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
if (i < (int)dc_clk_table->num_entries_per_clk.num_dcfclk_levels) {
int j, max_fclk = 0;
dml_clk_table->dcfclk.clk_values_khz[i] = dc_clk_table->entries[i].dcfclk_mhz * 1000;
for (j = 0; j < MAX_NUM_DPM_LVL; j++) {
if ((uint32_t)(dc_clk_table->entries[j].fclk_mhz * 1000) > (uint32_t)max_fclk)
max_fclk = dc_clk_table->entries[j].fclk_mhz * 1000;
dml_clk_table->fclk.clk_values_khz[i] = max_fclk;
if ((uint32_t)max_fclk >= 2 * dml_clk_table->dcfclk.clk_values_khz[i])
break;
}
} else {
dml_clk_table->dcfclk.clk_values_khz[i] = 0;
dml_clk_table->fclk.clk_values_khz[i] = 0;
}
}
}
if (dc_clk_table->num_entries_per_clk.num_memclk_levels) {
dml_clk_table->uclk.num_clk_values = (uint8_t)dc_clk_table->num_entries_per_clk.num_memclk_levels;
for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
if (i < dml_clk_table->uclk.num_clk_values) {
dml_clk_table->uclk.clk_values_khz[i] = dc_clk_table->entries[i].memclk_mhz * 1000;
dml_clk_table->wck_ratio.clk_values_khz[i] = dc_clk_table->entries[i].wck_ratio;
} else {
dml_clk_table->uclk.clk_values_khz[i] = 0;
dml_clk_table->wck_ratio.clk_values_khz[i] = 0;
}
}
}
if (dc_clk_table->num_entries_per_clk.num_dispclk_levels) {
dml_clk_table->dispclk.num_clk_values = (uint8_t)dc_clk_table->num_entries_per_clk.num_dispclk_levels;
for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
if (i < dml_clk_table->dispclk.num_clk_values) {
dml_clk_table->dispclk.clk_values_khz[i] = dc_clk_table->entries[i].dispclk_mhz * 1000;
} else {
dml_clk_table->dispclk.clk_values_khz[i] = 0;
}
}
vmin_limit->dispclk_khz = min(dc_clk_table->entries[0].dispclk_mhz * 1000, vmin_limit->dispclk_khz);
dml_clk_table->dispclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dispclk_levels >= 2 ? 2 : 1;
dml_clk_table->dispclk.clk_values_khz[0] = 0;
dml_clk_table->dispclk.clk_values_khz[1] = dc_clk_table->entries[dc_clk_table->num_entries_per_clk.num_dispclk_levels - 1].dispclk_mhz * 1000;
}
if (dc_clk_table->num_entries_per_clk.num_dppclk_levels) {
dml_clk_table->dppclk.num_clk_values = (uint8_t)dc_clk_table->num_entries_per_clk.num_dppclk_levels;
for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
if (i < dml_clk_table->dppclk.num_clk_values) {
dml_clk_table->dppclk.clk_values_khz[i] = dc_clk_table->entries[i].dppclk_mhz * 1000;
} else {
dml_clk_table->dppclk.clk_values_khz[i] = 0;
}
}
dml_clk_table->dppclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dppclk_levels >= 2 ? 2 : 1;
dml_clk_table->dppclk.clk_values_khz[0] = 0;
dml_clk_table->dppclk.clk_values_khz[1] = dc_clk_table->entries[dc_clk_table->num_entries_per_clk.num_dppclk_levels - 1].dppclk_mhz * 1000;
}
if (dc_clk_table->num_entries_per_clk.num_dtbclk_levels) {
dml_clk_table->dtbclk.num_clk_values = (uint8_t)dc_clk_table->num_entries_per_clk.num_dtbclk_levels;
for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
if (i < dml_clk_table->dtbclk.num_clk_values) {
dml_clk_table->dtbclk.clk_values_khz[i] = dc_clk_table->entries[i].dtbclk_mhz * 1000;
} else {
dml_clk_table->dtbclk.clk_values_khz[i] = 0;
}
}
}
if (dc_clk_table->num_entries_per_clk.num_socclk_levels) {
dml_clk_table->socclk.num_clk_values = (uint8_t)dc_clk_table->num_entries_per_clk.num_socclk_levels;
for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
if (i < dml_clk_table->socclk.num_clk_values) {
dml_clk_table->socclk.clk_values_khz[i] = dc_clk_table->entries[i].socclk_mhz * 1000;
} else {
dml_clk_table->socclk.clk_values_khz[i] = 0;
}
}
}
dml_clk_table->dram_config.channel_count = dc_bw_params->num_channels;
dml_clk_table->dram_config.channel_width_bytes = dc_bw_params->dram_channel_width_bytes;
}
static void dcn42_update_soc_bb_with_values_from_clk_mgr(struct dml2_soc_bb *soc_bb, const struct dc *dc)
{
soc_bb->dprefclk_mhz = dc->clk_mgr->dprefclk_khz / 1000;
soc_bb->dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
soc_bb->mall_allocated_for_dcn_mbytes = dc->caps.mall_size_total / (1024 * 1024);
if (dc->clk_mgr->funcs->is_smu_present &&
dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr)) {
dcn42_convert_dc_clock_table_to_soc_bb_clock_table(&soc_bb->clk_table, &soc_bb->vmin_limit,
dc->clk_mgr->bw_params);
}
if (dc->clk_mgr->bw_params->vram_type == Ddr5MemType) {
soc_bb->power_management_parameters = dcn42_ddr5_power_management_parameters;
}
}
static void apply_soc_bb_updates(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config)
{
(void)config;
dc_assert_fp_enabled();
dcn42_update_soc_bb_with_values_from_clk_mgr(soc_bb, dc);
dcn401_update_soc_bb_with_values_from_vbios(soc_bb, dc);
dcn401_update_soc_bb_with_values_from_software_policy(soc_bb, dc);
}
void dcn42_get_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config)
{
get_default_soc_bb(soc_bb, dc);
apply_soc_bb_updates(soc_bb, dc, config);
}
static void dcn42_get_ip_caps(struct dml2_ip_capabilities *ip_caps)
{
*ip_caps = dml2_dcn42_max_ip_caps;
}
static struct soc_and_ip_translator_funcs dcn42_translator_funcs = {
.get_soc_bb = dcn42_get_soc_bb,
.get_ip_caps = dcn42_get_ip_caps,
};
void dcn42_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and_ip_translator)
{
soc_and_ip_translator->translator_funcs = &dcn42_translator_funcs;
}