Commit 89c342a9 authored by Dmytro Laktyushkin's avatar Dmytro Laktyushkin Committed by Alex Deucher

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: default avatarQingqing Zhuo <Qingqing.Zhuo@amd.com>
Acked-by: default avatarTom Chung <chiahsuan.chung@amd.com>
Signed-off-by: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 259f249c
...@@ -219,8 +219,50 @@ static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *reg ...@@ -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 = { static struct clk_bw_params dcn315_bw_params = {
.vram_type = Ddr4MemType, .vram_type = Ddr4MemType,
.num_channels = 1, .num_channels = 2,
.clk_table = { .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, .num_entries = 5,
}, },
...@@ -300,8 +342,8 @@ static struct wm_table lpddr5_wm_table = { ...@@ -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 struct dcn315_watermarks dummy_wms = { 0 };
static void dcn315_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn315_watermarks *table) 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) ...@@ -415,22 +457,6 @@ static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks)
return max; 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( static void dcn315_clk_mgr_helper_populate_bw_params(
struct clk_mgr_internal *clk_mgr, struct clk_mgr_internal *clk_mgr,
struct integrated_info *bios_info, struct integrated_info *bios_info,
...@@ -438,13 +464,9 @@ static void dcn315_clk_mgr_helper_populate_bw_params( ...@@ -438,13 +464,9 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
{ {
int i; int i;
struct clk_bw_params *bw_params = clk_mgr->base.bw_params; 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]; 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 */ /* Find highest fclk pstate */
for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) { for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) {
if (clock_table->DfPstateTable[i].FClk > max_fclk) { if (clock_table->DfPstateTable[i].FClk > max_fclk) {
...@@ -466,35 +488,44 @@ static void dcn315_clk_mgr_helper_populate_bw_params( ...@@ -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].fclk_mhz = min_fclk;
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[min_pstate].MemClk; 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].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].dcfclk_mhz = clock_table->DcfClocks[i];
bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[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].dispclk_mhz = clock_table->DispClocks[i];
bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk; bw_params->clk_table.entries[i].dppclk_mhz = clock_table->DppClocks[i];
bw_params->clk_table.entries[i].wck_ratio = 1; bw_params->clk_table.entries[i].wck_ratio = 1;
}; };
/* Make sure to include at least one entry and highest pstate */ /* 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].fclk_mhz = max_fclk;
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk; 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].voltage = clock_table->DfPstateTable[max_pstate].Voltage;
bw_params->clk_table.entries[i].dcfclk_mhz = find_clk_for_voltage( bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS);
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; bw_params->clk_table.entries[i].wck_ratio = 1;
i++; i++;
} }
bw_params->clk_table.num_entries = i; bw_params->clk_table.num_entries = i--;
/* Include highest socclk */ /* Make sure all highest clocks are included*/
if (bw_params->clk_table.entries[i-1].socclk_mhz < max_socclk) 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-1].socclk_mhz = max_socclk; 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 /* Set any 0 clocks to max default setting. Not an issue for
* power since we aren't doing switching in such case anyway * power since we aren't doing switching in such case anyway
...@@ -513,9 +544,18 @@ static void dcn315_clk_mgr_helper_populate_bw_params( ...@@ -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; bw_params->clk_table.entries[i].dispclk_mhz = def_max.dispclk_mhz;
if (!bw_params->clk_table.entries[i].dppclk_mhz) if (!bw_params->clk_table.entries[i].dppclk_mhz)
bw_params->clk_table.entries[i].dppclk_mhz = def_max.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->vram_type = bios_info->memory_type;
bw_params->num_channels = bios_info->ma_channel_number; 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++) { for (i = 0; i < WM_SET_COUNT; i++) {
bw_params->wm_table.entries[i].wm_inst = i; bw_params->wm_table.entries[i].wm_inst = i;
......
...@@ -260,55 +260,6 @@ struct _vcs_dpi_ip_params_st dcn3_15_ip = { ...@@ -260,55 +260,6 @@ struct _vcs_dpi_ip_params_st dcn3_15_ip = {
}; };
struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = { struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
/*TODO: correct dispclk/dppclk voltage level determination*/
.clock_limits = {
{
.state = 0,
.dispclk_mhz = 1372.0,
.dppclk_mhz = 1372.0,
.phyclk_mhz = 810.0,
.phyclk_d18_mhz = 667.0,
.dscclk_mhz = 417.0,
.dtbclk_mhz = 600.0,
},
{
.state = 1,
.dispclk_mhz = 1372.0,
.dppclk_mhz = 1372.0,
.phyclk_mhz = 810.0,
.phyclk_d18_mhz = 667.0,
.dscclk_mhz = 417.0,
.dtbclk_mhz = 600.0,
},
{
.state = 2,
.dispclk_mhz = 1372.0,
.dppclk_mhz = 1372.0,
.phyclk_mhz = 810.0,
.phyclk_d18_mhz = 667.0,
.dscclk_mhz = 417.0,
.dtbclk_mhz = 600.0,
},
{
.state = 3,
.dispclk_mhz = 1372.0,
.dppclk_mhz = 1372.0,
.phyclk_mhz = 810.0,
.phyclk_d18_mhz = 667.0,
.dscclk_mhz = 417.0,
.dtbclk_mhz = 600.0,
},
{
.state = 4,
.dispclk_mhz = 1372.0,
.dppclk_mhz = 1372.0,
.phyclk_mhz = 810.0,
.phyclk_d18_mhz = 667.0,
.dscclk_mhz = 417.0,
.dtbclk_mhz = 600.0,
},
},
.num_states = 5,
.sr_exit_time_us = 9.0, .sr_exit_time_us = 9.0,
.sr_enter_plus_exit_time_us = 11.0, .sr_enter_plus_exit_time_us = 11.0,
.sr_exit_z8_time_us = 50.0, .sr_exit_z8_time_us = 50.0,
...@@ -696,23 +647,17 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params ...@@ -696,23 +647,17 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
{ {
struct clk_limit_table *clk_table = &bw_params->clk_table; struct clk_limit_table *clk_table = &bw_params->clk_table;
struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; int i, max_dispclk_mhz = 0, max_dppclk_mhz = 0;
unsigned int i, closest_clk_lvl;
int max_dispclk_mhz = 0, max_dppclk_mhz = 0;
int j;
dc_assert_fp_enabled(); dc_assert_fp_enabled();
// Default clock levels are used for diags, which may lead to overclocking.
if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
dcn3_15_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; dcn3_15_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
dcn3_15_ip.max_num_dpp = dc->res_pool->pipe_count; dcn3_15_ip.max_num_dpp = dc->res_pool->pipe_count;
dcn3_15_soc.num_chans = bw_params->num_channels; dcn3_15_soc.num_chans = bw_params->num_channels;
ASSERT(clk_table->num_entries); ASSERT(clk_table->num_entries);
/* Prepass to find max clocks independent of voltage level. */ /* Setup soc to always use max dispclk/dppclk to avoid odm-to-lower-voltage */
for (i = 0; i < clk_table->num_entries; ++i) { for (i = 0; i < clk_table->num_entries; ++i) {
if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz)
max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; max_dispclk_mhz = clk_table->entries[i].dispclk_mhz;
...@@ -721,55 +666,31 @@ void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param ...@@ -721,55 +666,31 @@ void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
} }
for (i = 0; i < clk_table->num_entries; i++) { for (i = 0; i < clk_table->num_entries; i++) {
/* loop backwards*/ dcn3_15_soc.clock_limits[i].state = i;
for (closest_clk_lvl = 0, j = dcn3_15_soc.num_states - 1; j >= 0; j--) {
if ((unsigned int) dcn3_15_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
closest_clk_lvl = j;
break;
}
}
if (clk_table->num_entries == 1) {
/*smu gives one DPM level, let's take the highest one*/
closest_clk_lvl = dcn3_15_soc.num_states - 1;
}
clock_limits[i].state = i;
/* Clocks dependent on voltage level. */ /* Clocks dependent on voltage level. */
clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; dcn3_15_soc.clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
if (clk_table->num_entries == 1 && dcn3_15_soc.clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
clock_limits[i].dcfclk_mhz < dcn3_15_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { dcn3_15_soc.clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
/*SMU fix not released yet*/ dcn3_15_soc.clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio;
clock_limits[i].dcfclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dcfclk_mhz;
}
clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio;
/* Clocks independent of voltage level. */ /* These aren't actually read from smu, but rather set in clk_mgr defaults */
clock_limits[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : dcn3_15_soc.clock_limits[i].dtbclk_mhz = clk_table->entries[i].dtbclk_mhz;
dcn3_15_soc.clock_limits[closest_clk_lvl].dispclk_mhz; dcn3_15_soc.clock_limits[i].phyclk_d18_mhz = clk_table->entries[i].phyclk_d18_mhz;
dcn3_15_soc.clock_limits[i].phyclk_mhz = clk_table->entries[i].phyclk_mhz;
clock_limits[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz :
dcn3_15_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
clock_limits[i].dram_bw_per_chan_gbps = dcn3_15_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; /* Clocks independent of voltage level. */
clock_limits[i].dscclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dscclk_mhz; dcn3_15_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz;
clock_limits[i].dtbclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; dcn3_15_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz;
clock_limits[i].phyclk_d18_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; dcn3_15_soc.clock_limits[i].dscclk_mhz = max_dispclk_mhz / 3.0;
clock_limits[i].phyclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
} }
for (i = 0; i < clk_table->num_entries; i++)
dcn3_15_soc.clock_limits[i] = clock_limits[i];
if (clk_table->num_entries) {
dcn3_15_soc.num_states = clk_table->num_entries; dcn3_15_soc.num_states = clk_table->num_entries;
}
}
if (max_dispclk_mhz) {
/* Set vco to max_dispclk * 2 to make sure the highest dispclk is always available for dml calcs,
* no impact outside of dml validation
*/
dcn3_15_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; dcn3_15_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2;
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2;
}
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31); dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31);
......
...@@ -91,6 +91,7 @@ struct clk_limit_table_entry { ...@@ -91,6 +91,7 @@ struct clk_limit_table_entry {
unsigned int dispclk_mhz; unsigned int dispclk_mhz;
unsigned int dppclk_mhz; unsigned int dppclk_mhz;
unsigned int phyclk_mhz; unsigned int phyclk_mhz;
unsigned int phyclk_d18_mhz;
unsigned int wck_ratio; unsigned int wck_ratio;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment