drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c- Extension
.c- Size
- 9416 bytes
- Lines
- 202
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
dml2_mcg_dcn4.hdml_top_soc_parameter_types.h
Detected Declarations
function mcg_dcn4_build_min_clock_tablefunction uclk_to_dram_bw_kbpsfunction round_up_to_quantized_valuesfunction build_min_clk_table_fine_grainedfunction build_min_clk_table_coarse_grainedfunction build_min_clock_table
Annotated Snippet
if (!fclk_fine_grained) {
min_table->dram_bw_table.entries[i].min_fclk_khz = round_up_to_quantized_values(min_table->dram_bw_table.entries[i].min_fclk_khz, soc_bb->clk_table.fclk.clk_values_khz, soc_bb->clk_table.fclk.num_clk_values);
}
}
min_table->dram_bw_table.entries[0].min_fclk_khz /= 2;
// Clamp to minimums and maximums
for (i = 0; i < (int)min_table->dram_bw_table.num_entries; i++) {
if (min_table->dram_bw_table.entries[i].min_dcfclk_khz < min_dcfclk_khz)
min_table->dram_bw_table.entries[i].min_dcfclk_khz = min_dcfclk_khz;
if (min_table->dram_bw_table.entries[i].min_fclk_khz < min_fclk_khz)
min_table->dram_bw_table.entries[i].min_fclk_khz = min_fclk_khz;
if (soc_bb->max_fclk_for_uclk_dpm_khz > 0 &&
min_table->dram_bw_table.entries[i].min_fclk_khz > soc_bb->max_fclk_for_uclk_dpm_khz)
min_table->dram_bw_table.entries[i].min_fclk_khz = soc_bb->max_fclk_for_uclk_dpm_khz;
min_table->dram_bw_table.entries[i].min_dcfclk_khz =
min_table->dram_bw_table.entries[i].min_fclk_khz *
soc_bb->qos_parameters.derate_table.system_active_urgent.fclk_derate_percent / soc_bb->qos_parameters.derate_table.system_active_urgent.dcfclk_derate_percent;
min_table->dram_bw_table.entries[i].min_dcfclk_khz =
min_table->dram_bw_table.entries[i].min_dcfclk_khz * soc_bb->fabric_datapath_to_dcn_data_return_bytes / soc_bb->return_bus_width_bytes;
if (!dcfclk_fine_grained) {
min_table->dram_bw_table.entries[i].min_dcfclk_khz = round_up_to_quantized_values(min_table->dram_bw_table.entries[i].min_dcfclk_khz, soc_bb->clk_table.dcfclk.clk_values_khz, soc_bb->clk_table.dcfclk.num_clk_values);
}
}
// Prune states which are invalid (some clocks exceed maximum)
for (i = 0; i < (int)min_table->dram_bw_table.num_entries; i++) {
if (min_table->dram_bw_table.entries[i].min_dcfclk_khz > min_table->max_clocks_khz.dcfclk ||
min_table->dram_bw_table.entries[i].min_fclk_khz > min_table->max_clocks_khz.fclk) {
min_table->dram_bw_table.num_entries = i;
break;
}
}
// Prune duplicate states
for (i = 0; i < (int)min_table->dram_bw_table.num_entries - 1; i++) {
if (min_table->dram_bw_table.entries[i].min_dcfclk_khz == min_table->dram_bw_table.entries[i + 1].min_dcfclk_khz &&
min_table->dram_bw_table.entries[i].min_fclk_khz == min_table->dram_bw_table.entries[i + 1].min_fclk_khz &&
min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps == min_table->dram_bw_table.entries[i + 1].pre_derate_dram_bw_kbps) {
// i + 1 is the same state as i, so shift everything
for (j = i + 1; j < min_table->dram_bw_table.num_entries; j++) {
min_table->dram_bw_table.entries[j].min_dcfclk_khz = min_table->dram_bw_table.entries[j + 1].min_dcfclk_khz;
min_table->dram_bw_table.entries[j].min_fclk_khz = min_table->dram_bw_table.entries[j + 1].min_fclk_khz;
min_table->dram_bw_table.entries[j].pre_derate_dram_bw_kbps = min_table->dram_bw_table.entries[j + 1].pre_derate_dram_bw_kbps;
}
min_table->dram_bw_table.num_entries--;
}
}
return true;
}
static bool build_min_clk_table_coarse_grained(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table)
{
int i;
for (i = 0; i < soc_bb->clk_table.uclk.num_clk_values; i++) {
min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps = uclk_to_dram_bw_kbps(soc_bb->clk_table.uclk.clk_values_khz[i], &soc_bb->clk_table.dram_config);
min_table->dram_bw_table.entries[i].min_dcfclk_khz = soc_bb->clk_table.dcfclk.clk_values_khz[i];
min_table->dram_bw_table.entries[i].min_fclk_khz = soc_bb->clk_table.fclk.clk_values_khz[i];
}
min_table->dram_bw_table.num_entries = soc_bb->clk_table.uclk.num_clk_values;
return true;
}
static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table)
{
bool result;
bool dcfclk_fine_grained = false, fclk_fine_grained = false, clock_state_count_equal = false;
if (!soc_bb || !min_table)
return false;
if (soc_bb->clk_table.dcfclk.num_clk_values < 2 || soc_bb->clk_table.fclk.num_clk_values < 2)
return false;
if (soc_bb->clk_table.uclk.num_clk_values > DML_MCG_MAX_CLK_TABLE_SIZE)
return false;
if (soc_bb->clk_table.dcfclk.num_clk_values == 2) {
dcfclk_fine_grained = true;
}
Annotation
- Immediate include surface: `dml2_mcg_dcn4.h`, `dml_top_soc_parameter_types.h`.
- Detected declarations: `function mcg_dcn4_build_min_clock_table`, `function uclk_to_dram_bw_kbps`, `function round_up_to_quantized_values`, `function build_min_clk_table_fine_grained`, `function build_min_clk_table_coarse_grained`, `function build_min_clock_table`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.