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.

Dependency Surface

Detected Declarations

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

Implementation Notes