drm/amd/display: update dcn315 clock table read

[Why & How]
Make dcn315 base its clock table off dcfclk rather than fclk.

This change also adds some sanity checking to make sure an
empty pmfw table does not result in invalid dal clocks.

Reviewed-by: Charlene Liu <Charlene.Liu@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Dmytro Laktyushkin 2022-03-30 16:05:50 -04:00 committed by Alex Deucher
parent 879791ad8b
commit 28c2523889
1 changed files with 67 additions and 40 deletions

View File

@ -436,57 +436,84 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
struct integrated_info *bios_info,
const DpmClocks_315_t *clock_table)
{
int i, j;
int i;
struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
uint32_t max_dispclk = 0, max_dppclk = 0;
uint32_t max_dispclk, max_dppclk, max_pstate, max_socclk, max_fclk = 0, min_pstate = 0;
struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1];
j = -1;
max_dispclk = find_max_clk_value(clock_table->DispClocks, clock_table->NumDispClkLevelsEnabled);
max_dppclk = find_max_clk_value(clock_table->DppClocks, clock_table->NumDispClkLevelsEnabled);
max_socclk = find_max_clk_value(clock_table->SocClocks, clock_table->NumSocClkLevelsEnabled);
ASSERT(NUM_DF_PSTATE_LEVELS <= MAX_NUM_DPM_LVL);
/* Find lowest DPM, FCLK is filled in reverse order*/
for (i = NUM_DF_PSTATE_LEVELS - 1; i >= 0; i--) {
if (clock_table->DfPstateTable[i].FClk != 0) {
j = i;
break;
/* Find highest fclk pstate */
for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) {
if (clock_table->DfPstateTable[i].FClk > max_fclk) {
max_fclk = clock_table->DfPstateTable[i].FClk;
max_pstate = i;
}
}
if (j == -1) {
/* clock table is all 0s, just use our own hardcode */
ASSERT(0);
return;
}
/* For 315 we want to base clock table on dcfclk, need at least one entry regardless of pmfw table */
for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) {
int j;
uint32_t min_fclk = clock_table->DfPstateTable[0].FClk;
bw_params->clk_table.num_entries = j + 1;
for (j = 1; j < clock_table->NumDfPstatesEnabled; j++) {
if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i]
&& clock_table->DfPstateTable[j].FClk < min_fclk) {
min_fclk = clock_table->DfPstateTable[j].FClk;
min_pstate = j;
}
}
/* dispclk and dppclk can be max at any voltage, same number of levels for both */
if (clock_table->NumDispClkLevelsEnabled <= NUM_DISPCLK_DPM_LEVELS &&
clock_table->NumDispClkLevelsEnabled <= NUM_DPPCLK_DPM_LEVELS) {
max_dispclk = find_max_clk_value(clock_table->DispClocks, clock_table->NumDispClkLevelsEnabled);
max_dppclk = find_max_clk_value(clock_table->DppClocks, clock_table->NumDispClkLevelsEnabled);
} else {
ASSERT(0);
}
for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) {
int temp;
bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[j].FClk;
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].MemClk;
bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].Voltage;
bw_params->clk_table.entries[i].wck_ratio = 1;
temp = find_clk_for_voltage(clock_table, clock_table->DcfClocks, clock_table->DfPstateTable[j].Voltage);
if (temp)
bw_params->clk_table.entries[i].dcfclk_mhz = temp;
temp = find_clk_for_voltage(clock_table, clock_table->SocClocks, clock_table->DfPstateTable[j].Voltage);
if (temp)
bw_params->clk_table.entries[i].socclk_mhz = temp;
bw_params->clk_table.entries[i].fclk_mhz = min_fclk;
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[min_pstate].MemClk;
bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[min_pstate].Voltage;
bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i];
bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i];
bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk;
bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk;
}
bw_params->clk_table.entries[i].wck_ratio = 1;
};
/* Make sure to include at least one entry and highest pstate */
if (max_pstate != min_pstate) {
bw_params->clk_table.entries[i].fclk_mhz = max_fclk;
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk;
bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[max_pstate].Voltage;
bw_params->clk_table.entries[i].dcfclk_mhz = find_clk_for_voltage(
clock_table, clock_table->DcfClocks, clock_table->DfPstateTable[max_pstate].Voltage);
bw_params->clk_table.entries[i].socclk_mhz = find_clk_for_voltage(
clock_table, clock_table->SocClocks, clock_table->DfPstateTable[max_pstate].Voltage);
bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk;
bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk;
bw_params->clk_table.entries[i].wck_ratio = 1;
i++;
}
bw_params->clk_table.num_entries = i;
/* Include highest socclk */
if (bw_params->clk_table.entries[i-1].socclk_mhz < max_socclk)
bw_params->clk_table.entries[i-1].socclk_mhz = max_socclk;
/* Set any 0 clocks to max default setting. Not an issue for
* power since we aren't doing switching in such case anyway
*/
for (i = 0; i < bw_params->clk_table.num_entries; i++) {
if (!bw_params->clk_table.entries[i].fclk_mhz) {
bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz;
bw_params->clk_table.entries[i].memclk_mhz = def_max.memclk_mhz;
bw_params->clk_table.entries[i].voltage = def_max.voltage;
}
if (!bw_params->clk_table.entries[i].dcfclk_mhz)
bw_params->clk_table.entries[i].dcfclk_mhz = def_max.dcfclk_mhz;
if (!bw_params->clk_table.entries[i].socclk_mhz)
bw_params->clk_table.entries[i].socclk_mhz = def_max.socclk_mhz;
if (!bw_params->clk_table.entries[i].dispclk_mhz)
bw_params->clk_table.entries[i].dispclk_mhz = def_max.dispclk_mhz;
if (!bw_params->clk_table.entries[i].dppclk_mhz)
bw_params->clk_table.entries[i].dppclk_mhz = def_max.dppclk_mhz;
}
bw_params->vram_type = bios_info->memory_type;
bw_params->num_channels = bios_info->ma_channel_number;