drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c- Extension
.c- Size
- 16517 bytes
- Lines
- 488
- 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
resource.hclk_mgr.hdcn20/dcn20_resource.hdcn301/dcn301_resource.hclk_mgr/dcn301/vg_clk_mgr.hdml/dcn20/dcn20_fpu.hdcn301_fpu.h
Detected Declarations
function calculate_wm_set_for_vlevelfunction dcn301_fpu_update_bw_bounding_boxfunction dcn301_fpu_set_wm_rangesfunction dcn301_fpu_init_soc_bounding_boxfunction dcn301_fpu_calculate_wm_and_dlg
Annotated Snippet
if ((unsigned int) dcn3_01_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
closest_clk_lvl = j;
break;
}
}
s[i].state = i;
s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
s[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
/* Clocks independent of voltage level. */
s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz :
dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
s[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz :
dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
s[i].dram_bw_per_chan_gbps =
dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
s[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
s[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
s[i].phyclk_d18_mhz =
dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
s[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
}
if (clk_table->num_entries) {
dcn3_01_soc.num_states = clk_table->num_entries;
/* duplicate last level */
s[dcn3_01_soc.num_states] =
dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1];
s[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states;
}
memcpy(dcn3_01_soc.clock_limits, s, sizeof(dcn3_01_soc.clock_limits));
dcn3_01_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
if ((int)(dcn3_01_soc.dram_clock_change_latency_us * 1000)
!= dc->debug.dram_clock_change_latency_ns
&& dc->debug.dram_clock_change_latency_ns) {
dcn3_01_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000.0;
}
dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
}
void dcn301_fpu_set_wm_ranges(int i,
struct pp_smu_wm_range_sets *ranges,
struct _vcs_dpi_soc_bounding_box_st *loaded_bb)
{
dc_assert_fp_enabled();
ranges->reader_wm_sets[i].min_fill_clk_mhz = (uint16_t)((i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0);
ranges->reader_wm_sets[i].max_fill_clk_mhz = (uint16_t)(loaded_bb->clock_limits[i].dram_speed_mts / 16);
}
void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info)
{
dc_assert_fp_enabled();
if (bb_info.dram_clock_change_latency_100ns > 0)
dcn3_01_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
dcn3_01_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
if (bb_info.dram_sr_exit_latency_100ns > 0)
dcn3_01_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
}
void dcn301_fpu_calculate_wm_and_dlg(struct dc *dc,
struct dc_state *context,
display_e2e_pipe_params_st *pipes,
int pipe_cnt,
int vlevel_req)
{
unsigned int i, pipe_idx;
int vlevel, vlevel_max;
struct wm_range_table_entry *table_entry;
struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
ASSERT(bw_params);
dc_assert_fp_enabled();
vlevel_max = bw_params->clk_table.num_entries - 1;
/* WM Set D */
Annotation
- Immediate include surface: `resource.h`, `clk_mgr.h`, `dcn20/dcn20_resource.h`, `dcn301/dcn301_resource.h`, `clk_mgr/dcn301/vg_clk_mgr.h`, `dml/dcn20/dcn20_fpu.h`, `dcn301_fpu.h`.
- Detected declarations: `function calculate_wm_set_for_vlevel`, `function dcn301_fpu_update_bw_bounding_box`, `function dcn301_fpu_set_wm_ranges`, `function dcn301_fpu_init_soc_bounding_box`, `function dcn301_fpu_calculate_wm_and_dlg`.
- 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.