From 89c342a9661838b9afe3988418705f877f496928 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 8 Apr 2022 10:10:04 -0400 Subject: drm/amd/display: update dcn315 clk table read Clean up the sequence by making sure clk_mgr always builds a reasonable clock table regardless of what we read from smu by moving all defaults from resource soc struct to clk_mgr. Now the only thing resource soc update does is read the clock table and apply any DC specific policy decisions to how clocks are populated in dml soc. Reviewed-by: Qingqing Zhuo Acked-by: Tom Chung Signed-off-by: Dmytro Laktyushkin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 114 ++++++++++++++------- 1 file changed, 77 insertions(+), 37 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 8be4c1970628..27501b735a9c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -219,8 +219,50 @@ static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *reg static struct clk_bw_params dcn315_bw_params = { .vram_type = Ddr4MemType, - .num_channels = 1, + .num_channels = 2, .clk_table = { + .entries = { + { + .voltage = 0, + .dispclk_mhz = 640, + .dppclk_mhz = 640, + .phyclk_mhz = 810, + .phyclk_d18_mhz = 667, + .dtbclk_mhz = 600, + }, + { + .voltage = 1, + .dispclk_mhz = 739, + .dppclk_mhz = 739, + .phyclk_mhz = 810, + .phyclk_d18_mhz = 667, + .dtbclk_mhz = 600, + }, + { + .voltage = 2, + .dispclk_mhz = 960, + .dppclk_mhz = 960, + .phyclk_mhz = 810, + .phyclk_d18_mhz = 667, + .dtbclk_mhz = 600, + }, + { + .voltage = 3, + .dispclk_mhz = 1200, + .dppclk_mhz = 1200, + .phyclk_mhz = 810, + .phyclk_d18_mhz = 667, + .dtbclk_mhz = 600, + }, + { + .voltage = 4, + .dispclk_mhz = 1372, + .dppclk_mhz = 1372, + .phyclk_mhz = 810, + .phyclk_d18_mhz = 667, + .dtbclk_mhz = 600, + }, + }, .num_entries = 5, }, @@ -300,8 +342,8 @@ static struct wm_table lpddr5_wm_table = { } }; -static DpmClocks_315_t dummy_clocks; - +/* Temporary Place holder until we can get them from fuse */ +static DpmClocks_315_t dummy_clocks = { 0 }; static struct dcn315_watermarks dummy_wms = { 0 }; static void dcn315_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn315_watermarks *table) @@ -415,22 +457,6 @@ static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks) return max; } -static unsigned int find_clk_for_voltage( - const DpmClocks_315_t *clock_table, - const uint32_t clocks[], - unsigned int voltage) -{ - int i; - - for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) { - if (clock_table->SocVoltage[i] == voltage) - return clocks[i]; - } - - ASSERT(0); - return 0; -} - static void dcn315_clk_mgr_helper_populate_bw_params( struct clk_mgr_internal *clk_mgr, struct integrated_info *bios_info, @@ -438,13 +464,9 @@ static void dcn315_clk_mgr_helper_populate_bw_params( { int i; struct clk_bw_params *bw_params = clk_mgr->base.bw_params; - uint32_t max_dispclk, max_dppclk, max_pstate, max_socclk, max_fclk = 0, min_pstate = 0; + uint32_t max_pstate = 0, 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]; - 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); - /* Find highest fclk pstate */ for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) { if (clock_table->DfPstateTable[i].FClk > max_fclk) { @@ -466,35 +488,44 @@ static void dcn315_clk_mgr_helper_populate_bw_params( } } + /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */ + for (j = bw_params->clk_table.num_entries - 1; j > 0; j--) + if (bw_params->clk_table.entries[j].dcfclk_mhz <= clock_table->DcfClocks[i]) + break; + bw_params->clk_table.entries[i].phyclk_mhz = bw_params->clk_table.entries[j].phyclk_mhz; + bw_params->clk_table.entries[i].phyclk_d18_mhz = bw_params->clk_table.entries[j].phyclk_d18_mhz; + bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz; + + /* Now update clocks we do read */ 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].dispclk_mhz = clock_table->DispClocks[i]; + bw_params->clk_table.entries[i].dppclk_mhz = clock_table->DppClocks[i]; 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) { + if (max_pstate != min_pstate || i == 0) { 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].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS); bw_params->clk_table.entries[i].wck_ratio = 1; i++; } - bw_params->clk_table.num_entries = 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; + /* Make sure all highest clocks are included*/ + bw_params->clk_table.entries[i].socclk_mhz = find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS); + bw_params->clk_table.entries[i].dispclk_mhz = find_max_clk_value(clock_table->DispClocks, NUM_DISPCLK_DPM_LEVELS); + bw_params->clk_table.entries[i].dppclk_mhz = find_max_clk_value(clock_table->DppClocks, NUM_DPPCLK_DPM_LEVELS); + ASSERT(clock_table->DcfClocks[i] == find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS)); + bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz; + bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz; + bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; /* Set any 0 clocks to max default setting. Not an issue for * power since we aren't doing switching in such case anyway @@ -513,9 +544,18 @@ static void dcn315_clk_mgr_helper_populate_bw_params( 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; + if (!bw_params->clk_table.entries[i].phyclk_mhz) + bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz; + if (!bw_params->clk_table.entries[i].phyclk_d18_mhz) + bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz; + if (!bw_params->clk_table.entries[i].dtbclk_mhz) + bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; } + ASSERT(bw_params->clk_table.entries[i].dcfclk_mhz); bw_params->vram_type = bios_info->memory_type; bw_params->num_channels = bios_info->ma_channel_number; + if (!bw_params->num_channels) + bw_params->num_channels = 2; for (i = 0; i < WM_SET_COUNT; i++) { bw_params->wm_table.entries[i].wm_inst = i; -- cgit v1.2.3