drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
Extension
.c
Size
31173 bytes
Lines
831
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 (dc->config.forced_clocks || dc->debug.max_disp_clk) {
			pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
			pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
		}
		if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
			pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
		if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
			pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;

		pipe_idx++;
	}

	dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
	/* For 31x apu pstate change is only supported if possible in vactive*/
	context->bw_ctx.bw.dcn.clk.p_state_change_support =
			context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_vactive;
	/* If DCN isn't making memory requests we can allow pstate change and lower clocks */
	if (!active_hubp_count) {
		context->bw_ctx.bw.dcn.clk.socclk_khz = 0;
		context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
		context->bw_ctx.bw.dcn.clk.dcfclk_khz = 0;
		context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = 0;
		context->bw_ctx.bw.dcn.clk.dramclk_khz = 0;
		context->bw_ctx.bw.dcn.clk.fclk_khz = 0;
		context->bw_ctx.bw.dcn.clk.p_state_change_support = true;
		for (i = 0; i < dc->res_pool->pipe_count; i++)
			if (context->res_ctx.pipe_ctx[i].stream)
				context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = 0;
	}
	for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
		if (!context->res_ctx.pipe_ctx[i].stream)
			continue;

		context->res_ctx.pipe_ctx[i].det_buffer_size_kb =
				(int)get_det_buffer_size_kbytes(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
		if (context->res_ctx.pipe_ctx[i].det_buffer_size_kb > 384)
			context->res_ctx.pipe_ctx[i].det_buffer_size_kb /= 2;
		total_det += context->res_ctx.pipe_ctx[i].det_buffer_size_kb;
		pipe_idx++;
	}
	context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - total_det;
}

void dcn31_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params)
{
	struct _vcs_dpi_voltage_scaling_st *s = dc->scratch.update_bw_bounding_box.clock_limits;
	struct clk_limit_table *clk_table = &bw_params->clk_table;
	unsigned int i, closest_clk_lvl;
	unsigned int max_dispclk_mhz = 0, max_dppclk_mhz = 0;
	int j;

	dc_assert_fp_enabled();

	memcpy(s, dcn3_1_soc.clock_limits, sizeof(dcn3_1_soc.clock_limits));

	// Default clock levels are used for diags, which may lead to overclocking.
	dcn3_1_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
	dcn3_1_ip.max_num_dpp = dc->res_pool->pipe_count;
	dcn3_1_soc.num_chans = bw_params->num_channels;

	ASSERT(clk_table->num_entries);

	/* Prepass to find max clocks independent of voltage level. */
	for (i = 0; i < clk_table->num_entries; ++i) {
		if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz)
			max_dispclk_mhz = clk_table->entries[i].dispclk_mhz;
		if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz)
			max_dppclk_mhz = clk_table->entries[i].dppclk_mhz;
	}

	for (i = 0; i < clk_table->num_entries; i++) {
		/* loop backwards*/
		for (closest_clk_lvl = 0, j = dcn3_1_soc.num_states - 1; j >= 0; j--) {
			if ((unsigned int) dcn3_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
				closest_clk_lvl = j;
				break;
			}
		}

		s[i].state = i;

		/* Clocks dependent on voltage level. */
		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 * clk_table->entries[i].wck_ratio;

		/* Clocks independent of voltage level. */
		s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz :

Annotation

Implementation Notes