Skip to content

Commit d60f56b

Browse files
Nicholas Kazlauskasalexdeucher
authored andcommitted
drm/amd/display: Update DCN35 clock table policy
[Why] The new table doesn't have an implicit mapping between Fclk SOC voltage and MemClk and it currently builds the table off of number of Fclk states rather than DcfClock states. The DML table in use is not correct for functionality or power and does not align with our existing policies for DCN3x. [How] Build the table based on DcfClock with the following assumptions: 1. Raising Soc voltage is the most expensive operation, so assume that running at max DispClock or DppClock is preferable. 2. Assume that we can run at max Fclk / MemClk at any state, but restrict the maximum state to the very last entry in the table as the worst case scenario. 3. Assume that Fclk always has a 2x multiplier on DcfClock unless the table specifies something lower. Reviewed-by: Taimur Hassan <[email protected]> Acked-by: Hamza Mahfooz <[email protected]> Signed-off-by: Nicholas Kazlauskas <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent eb28018 commit d60f56b

File tree

1 file changed

+51
-26
lines changed

1 file changed

+51
-26
lines changed

drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -648,27 +648,47 @@ static unsigned int convert_wck_ratio(uint8_t wck_ratio)
648648
return 1;
649649
}
650650

651+
static inline uint32_t calc_dram_speed_mts(const MemPstateTable_t *entry)
652+
{
653+
return entry->UClk * convert_wck_ratio(entry->WckRatio) * 2;
654+
}
655+
651656
static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk_mgr,
652657
struct integrated_info *bios_info,
653658
DpmClocks_t_dcn35 *clock_table)
654659
{
655660
struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
656661
struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1];
657-
uint32_t max_pstate = 0, max_uclk = 0, max_fclk = 0;
658-
uint32_t min_pstate = 0, max_dispclk = 0, max_dppclk = 0;
662+
uint32_t max_fclk = 0, min_pstate = 0, max_dispclk = 0, max_dppclk = 0;
663+
uint32_t max_pstate = 0, max_dram_speed_mts = 0, min_dram_speed_mts = 0;
659664
int i;
660665

666+
/* Determine min/max p-state values. */
661667
for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
662-
if (is_valid_clock_value(clock_table->MemPstateTable[i].UClk) &&
663-
clock_table->MemPstateTable[i].UClk > max_uclk) {
664-
max_uclk = clock_table->MemPstateTable[i].UClk;
668+
uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]);
669+
670+
if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts > max_dram_speed_mts) {
671+
max_dram_speed_mts = dram_speed_mts;
665672
max_pstate = i;
666673
}
667674
}
668675

669-
/* We expect the table to contain at least one valid Uclk entry. */
670-
ASSERT(is_valid_clock_value(max_uclk));
676+
min_dram_speed_mts = max_dram_speed_mts;
677+
min_pstate = max_pstate;
671678

679+
for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
680+
uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]);
681+
682+
if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts < min_dram_speed_mts) {
683+
min_dram_speed_mts = dram_speed_mts;
684+
min_pstate = i;
685+
}
686+
}
687+
688+
/* We expect the table to contain at least one valid P-state entry. */
689+
ASSERT(clock_table->NumMemPstatesEnabled &&
690+
is_valid_clock_value(max_dram_speed_mts) &&
691+
is_valid_clock_value(min_dram_speed_mts));
672692

673693
/* dispclk and dppclk can be max at any voltage, same number of levels for both */
674694
if (clock_table->NumDispClkLevelsEnabled <= NUM_DISPCLK_DPM_LEVELS &&
@@ -678,47 +698,46 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk
678698
max_dppclk = find_max_clk_value(clock_table->DppClocks,
679699
clock_table->NumDispClkLevelsEnabled);
680700
} else {
701+
/* Invalid number of entries in the table from PMFW. */
681702
ASSERT(0);
682703
}
683-
if (clock_table->NumFclkLevelsEnabled <= NUM_FCLK_DPM_LEVELS)
684-
max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq,
685-
clock_table->NumFclkLevelsEnabled);
686704

687-
for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
688-
uint32_t min_uclk = clock_table->MemPstateTable[0].UClk;
689-
int j;
705+
/* Base the clock table on dcfclk, need at least one entry regardless of pmfw table */
706+
ASSERT(clock_table->NumDcfClkLevelsEnabled > 0);
690707

691-
for (j = 1; j < clock_table->NumMemPstatesEnabled; j++) {
692-
if (is_valid_clock_value(clock_table->MemPstateTable[j].UClk) &&
693-
clock_table->MemPstateTable[j].UClk < min_uclk &&
694-
clock_table->MemPstateTable[j].Voltage <= clock_table->SocVoltage[i]) {
695-
min_uclk = clock_table->MemPstateTable[j].UClk;
696-
min_pstate = j;
697-
}
698-
}
708+
max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq, clock_table->NumFclkLevelsEnabled);
699709

710+
for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) {
711+
int j;
712+
713+
/* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */
700714
for (j = bw_params->clk_table.num_entries - 1; j > 0; j--)
701715
if (bw_params->clk_table.entries[j].dcfclk_mhz <= clock_table->DcfClocks[i])
702-
break;
716+
break;
703717

704718
bw_params->clk_table.entries[i].phyclk_mhz = bw_params->clk_table.entries[j].phyclk_mhz;
705719
bw_params->clk_table.entries[i].phyclk_d18_mhz = bw_params->clk_table.entries[j].phyclk_d18_mhz;
706720
bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz;
707-
bw_params->clk_table.entries[i].fclk_mhz = max_fclk;
721+
722+
/* Now update clocks we do read */
708723
bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemPstateTable[min_pstate].MemClk;
709724
bw_params->clk_table.entries[i].voltage = clock_table->MemPstateTable[min_pstate].Voltage;
710725
bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i];
711726
bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i];
712727
bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk;
713728
bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk;
714-
bw_params->clk_table.entries[i].wck_ratio = convert_wck_ratio(
715-
clock_table->MemPstateTable[min_pstate].WckRatio);
716-
}
729+
bw_params->clk_table.entries[i].wck_ratio =
730+
convert_wck_ratio(clock_table->MemPstateTable[min_pstate].WckRatio);
731+
732+
/* Dcfclk and Fclk are tied, but at a different ratio */
733+
bw_params->clk_table.entries[i].fclk_mhz = min(max_fclk, 2 * clock_table->DcfClocks[i]);
734+
}
717735

718736
/* Make sure to include at least one entry at highest pstate */
719737
if (max_pstate != min_pstate || i == 0) {
720738
if (i > MAX_NUM_DPM_LVL - 1)
721739
i = MAX_NUM_DPM_LVL - 1;
740+
722741
bw_params->clk_table.entries[i].fclk_mhz = max_fclk;
723742
bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemPstateTable[max_pstate].MemClk;
724743
bw_params->clk_table.entries[i].voltage = clock_table->MemPstateTable[max_pstate].Voltage;
@@ -734,6 +753,7 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk
734753
}
735754
bw_params->clk_table.num_entries = i--;
736755

756+
/* Make sure all highest clocks are included*/
737757
bw_params->clk_table.entries[i].socclk_mhz =
738758
find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS);
739759
bw_params->clk_table.entries[i].dispclk_mhz =
@@ -752,6 +772,11 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk
752772
bw_params->clk_table.num_entries_per_clk.num_fclk_levels = clock_table->NumFclkLevelsEnabled;
753773
bw_params->clk_table.num_entries_per_clk.num_memclk_levels = clock_table->NumMemPstatesEnabled;
754774
bw_params->clk_table.num_entries_per_clk.num_socclk_levels = clock_table->NumSocClkLevelsEnabled;
775+
776+
/*
777+
* Set any 0 clocks to max default setting. Not an issue for
778+
* power since we aren't doing switching in such case anyway
779+
*/
755780
for (i = 0; i < bw_params->clk_table.num_entries; i++) {
756781
if (!bw_params->clk_table.entries[i].fclk_mhz) {
757782
bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz;

0 commit comments

Comments
 (0)