mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
drm/amd/display: add dcn42b specific SMU clock table read
[Why] On DCN42B the SMU reports its DpmClocks table in a different layout than DCN42, with extra clock domains. The clk_mgr was parsing it with the DCN42 layout. [How] Add a DCN42B DpmClocks struct and a dcn42b_get_smu_clocks() that allocates and parses the DCN42B layout, reusing the shared dcn42 helpers so DCN42 is untouched. Populate DCF, SOC, DISP, DPP and FCLK levels and the memory pstate table. Reviewed-by: Charlene Liu <charlene.liu@amd.com> Signed-off-by: Gabe Teeger <gabe.teeger@amd.com> Signed-off-by: Matthew Stewart <matthew.stewart2@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
8ba869e852
commit
84beee0dd2
|
|
@ -221,10 +221,6 @@ static void init_clk_states(struct clk_mgr *clk_mgr)
|
|||
clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
|
||||
}
|
||||
|
||||
/* dcn42b_get_dpm_table_from_smu removed: reuse dcn42_get_dpm_table_from_smu.
|
||||
* Function is identical - only uses SMU calls, no hardware register differences.
|
||||
*/
|
||||
|
||||
void dcn42b_init_clocks(struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
|
|
@ -412,6 +408,176 @@ static struct clk_mgr_funcs dcn42b_funcs = {
|
|||
.is_smu_present = dcn42_is_smu_present,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS];
|
||||
uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS];
|
||||
uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS];
|
||||
uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS];
|
||||
uint32_t VPEClocks[NUM_VPE_DPM_LEVELS];
|
||||
uint32_t FclkClocks_Freq[NUM_FCLK_DPM_LEVELS];
|
||||
uint32_t FclkClocks_Voltage[NUM_FCLK_DPM_LEVELS];
|
||||
uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS];
|
||||
MemPstateTable_t MemPstateTable[NUM_MEM_PSTATE_LEVELS];
|
||||
|
||||
uint8_t NumDcfClkLevelsEnabled;
|
||||
uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk
|
||||
uint8_t NumSocClkLevelsEnabled;
|
||||
uint8_t VpeClkLevelsEnabled;
|
||||
|
||||
uint8_t NumMemPstatesEnabled;
|
||||
uint8_t NumFclkLevelsEnabled;
|
||||
uint8_t Spare1;
|
||||
uint8_t Spare2;
|
||||
|
||||
uint8_t Spare3;
|
||||
uint8_t Spare4;
|
||||
uint8_t Spare5[2];
|
||||
|
||||
uint32_t MinGfxClk;
|
||||
uint32_t MaxGfxClk;
|
||||
|
||||
uint32_t Spare6[8];
|
||||
uint32_t Spare7[8];
|
||||
uint32_t Spare8[8];
|
||||
uint32_t Spare9[8];
|
||||
} DpmClocks_t_dcn42b;
|
||||
struct dcn42b_smu_dpm_clks {
|
||||
DpmClocks_t_dcn42b *dpm_clks;
|
||||
union large_integer mc_address;
|
||||
};
|
||||
|
||||
static void dcn42b_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
|
||||
struct dcn42b_smu_dpm_clks *smu_dpm_clks)
|
||||
{
|
||||
DpmClocks_t_dcn42b *table = smu_dpm_clks->dpm_clks;
|
||||
|
||||
if (!clk_mgr->smu_ver)
|
||||
return;
|
||||
|
||||
if (!table || smu_dpm_clks->mc_address.quad_part == 0)
|
||||
return;
|
||||
|
||||
memset(table, 0, sizeof(*table));
|
||||
|
||||
dcn42_smu_set_dram_addr_high(clk_mgr,
|
||||
smu_dpm_clks->mc_address.high_part);
|
||||
dcn42_smu_set_dram_addr_low(clk_mgr,
|
||||
smu_dpm_clks->mc_address.low_part);
|
||||
dcn42_smu_transfer_dpm_table_smu_2_dram(clk_mgr);
|
||||
}
|
||||
|
||||
static void dcn42b_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int)
|
||||
{
|
||||
struct clk_mgr *clk_mgr_base = &clk_mgr_int->base;
|
||||
struct dcn42b_smu_dpm_clks smu_dpm_clks = { 0 };
|
||||
|
||||
DC_LOGGER_INIT(clk_mgr_base->ctx->logger);
|
||||
(void)dc_logger;
|
||||
|
||||
smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn42b *)dm_helpers_allocate_gpu_mem(
|
||||
clk_mgr_base->ctx,
|
||||
DC_MEM_ALLOC_TYPE_GART,
|
||||
sizeof(DpmClocks_t_dcn42b),
|
||||
&smu_dpm_clks.mc_address.quad_part);
|
||||
|
||||
ASSERT(smu_dpm_clks.dpm_clks);
|
||||
if (clk_mgr_base->ctx->dc->debug.pstate_enabled && smu_dpm_clks.mc_address.quad_part != 0) {
|
||||
int i;
|
||||
DpmClocks_t_dcn42b *dpm_clks = smu_dpm_clks.dpm_clks;
|
||||
|
||||
dcn42b_get_dpm_table_from_smu(clk_mgr_int, &smu_dpm_clks);
|
||||
DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n"
|
||||
"NumDispClkLevelsEnabled: %d\n"
|
||||
"NumSocClkLevelsEnabled: %d\n"
|
||||
"VpeClkLevelsEnabled: %d\n"
|
||||
"FClkLevelsEnabled: %d\n"
|
||||
"NumMemPstatesEnabled: %d\n"
|
||||
"MinGfxClk: %d\n"
|
||||
"MaxGfxClk: %d\n",
|
||||
dpm_clks->NumDcfClkLevelsEnabled,
|
||||
dpm_clks->NumDispClkLevelsEnabled,
|
||||
dpm_clks->NumSocClkLevelsEnabled,
|
||||
dpm_clks->VpeClkLevelsEnabled,
|
||||
dpm_clks->NumFclkLevelsEnabled,
|
||||
dpm_clks->NumMemPstatesEnabled,
|
||||
dpm_clks->MinGfxClk,
|
||||
dpm_clks->MaxGfxClk);
|
||||
|
||||
for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++)
|
||||
DC_LOG_SMU("dpm_clks->DcfClocks[%d] = %d\n", i, dpm_clks->DcfClocks[i]);
|
||||
for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++)
|
||||
DC_LOG_SMU("dpm_clks->DispClocks[%d] = %d\n", i, dpm_clks->DispClocks[i]);
|
||||
for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++)
|
||||
DC_LOG_SMU("dpm_clks->SocClocks[%d] = %d\n", i, dpm_clks->SocClocks[i]);
|
||||
for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
|
||||
DC_LOG_SMU("dpm_clks->FclkClocks_Freq[%d] = %d\n", i, dpm_clks->FclkClocks_Freq[i]);
|
||||
DC_LOG_SMU("dpm_clks->FclkClocks_Voltage[%d] = %d\n", i, dpm_clks->FclkClocks_Voltage[i]);
|
||||
}
|
||||
for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++)
|
||||
DC_LOG_SMU("dpm_clks->SocVoltage[%d] = %d\n", i, dpm_clks->SocVoltage[i]);
|
||||
|
||||
for (i = 0; i < NUM_MEM_PSTATE_LEVELS; i++)
|
||||
DC_LOG_SMU("dpm_clks.MemPstateTable[%d].UClk = %d MemClk = %d Voltage = %d\n",
|
||||
i, dpm_clks->MemPstateTable[i].UClk, dpm_clks->MemPstateTable[i].MemClk, dpm_clks->MemPstateTable[i].Voltage);
|
||||
|
||||
if (clk_mgr_base->ctx->dc_bios->integrated_info && clk_mgr_base->ctx->dc->config.use_default_clock_table == false) {
|
||||
/* DCFCLK */
|
||||
dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
|
||||
dpm_clks->DcfClocks,
|
||||
dpm_clks->NumDcfClkLevelsEnabled);
|
||||
clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels = dpm_clks->NumDcfClkLevelsEnabled;
|
||||
|
||||
/* SOCCLK */
|
||||
dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
|
||||
dpm_clks->SocClocks,
|
||||
dpm_clks->NumSocClkLevelsEnabled);
|
||||
clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_socclk_levels = dpm_clks->NumSocClkLevelsEnabled;
|
||||
|
||||
/* DISPCLK */
|
||||
dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
|
||||
dpm_clks->DispClocks,
|
||||
dpm_clks->NumDispClkLevelsEnabled);
|
||||
clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels = dpm_clks->NumDispClkLevelsEnabled;
|
||||
|
||||
/* DPPCLK */
|
||||
dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz,
|
||||
dpm_clks->DppClocks,
|
||||
dpm_clks->NumDispClkLevelsEnabled);
|
||||
clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels = dpm_clks->NumDispClkLevelsEnabled;
|
||||
|
||||
/* FCLK */
|
||||
dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
|
||||
dpm_clks->FclkClocks_Freq,
|
||||
NUM_FCLK_DPM_LEVELS);
|
||||
clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels = dpm_clks->NumFclkLevelsEnabled;
|
||||
clk_mgr_base->bw_params->clk_table.num_entries = dpm_clks->NumFclkLevelsEnabled;
|
||||
|
||||
/* Memory Pstate table is in reverse order for dcn42. Proper way to map this is for pmfw to provide an fclk indexed uclk key since we consume fclk matched pairs.*/
|
||||
ASSERT(dpm_clks->NumMemPstatesEnabled <= NUM_MEM_PSTATE_LEVELS);
|
||||
if (dpm_clks->NumMemPstatesEnabled > NUM_MEM_PSTATE_LEVELS)
|
||||
dpm_clks->NumMemPstatesEnabled = NUM_MEM_PSTATE_LEVELS;
|
||||
for (i = 0; i < dpm_clks->NumDcfClkLevelsEnabled; i++) {
|
||||
if (i < dpm_clks->NumMemPstatesEnabled) {
|
||||
clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].memclk_mhz = dpm_clks->MemPstateTable[i].MemClk;
|
||||
clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].wck_ratio = dcn42_convert_wck_ratio(dpm_clks->MemPstateTable[i].WckRatio);
|
||||
} else {
|
||||
clk_mgr_base->bw_params->clk_table.entries[i].memclk_mhz = dpm_clks->MemPstateTable[0].MemClk;
|
||||
clk_mgr_base->bw_params->clk_table.entries[i].wck_ratio = dcn42_convert_wck_ratio(dpm_clks->MemPstateTable[0].WckRatio);
|
||||
}
|
||||
}
|
||||
|
||||
clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels = dpm_clks->NumDcfClkLevelsEnabled;
|
||||
|
||||
/* DTBCLK tied off in DCN42B */
|
||||
clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz = 0;
|
||||
clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 0;
|
||||
}
|
||||
}
|
||||
if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0)
|
||||
dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART,
|
||||
smu_dpm_clks.dpm_clks);
|
||||
}
|
||||
|
||||
void dcn42b_clk_mgr_construct(
|
||||
struct dc_context *ctx,
|
||||
struct clk_mgr_dcn42 *clk_mgr,
|
||||
|
|
@ -473,11 +639,6 @@ void dcn42b_clk_mgr_construct(
|
|||
dcn42b_read_ss_info_from_lut(&clk_mgr->base);
|
||||
|
||||
clk_mgr->base.base.bw_params = &dcn42b_bw_params;
|
||||
if (clk_mgr->base.smu_present) {
|
||||
dcn42_get_smu_clocks(&clk_mgr->base);
|
||||
//overwrite values from dcn42_get_smu_clocks since dtbclk is tied off in DCN42B
|
||||
clk_mgr->base.base.bw_params->clk_table.entries[0].dtbclk_mhz = 0;
|
||||
clk_mgr->base.base.bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 0;
|
||||
clk_mgr->base.base.clks.ref_dtbclk_khz = 0;
|
||||
}
|
||||
if (clk_mgr->base.smu_present)
|
||||
dcn42b_get_smu_clocks(&clk_mgr->base);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user