drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
Extension
.c
Size
39983 bytes
Lines
1121
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

else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) {
			/* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting.
			 * In this case just continue in loop
			 */
			continue;
		} else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) {
			/* The software state is not valid if dpp resource is NULL and
			 * dppclk_khz > 0.
			 */
			ASSERT(false);
			continue;
		}

		prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i];

		if (safe_to_lower || prev_dppclk_khz < dppclk_khz)
			clk_mgr->dccg->funcs->update_dpp_dto(
							clk_mgr->dccg, dpp_inst, dppclk_khz);
		dppclk_active[dpp_inst] = true;
	}
	if (safe_to_lower)
		for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
			struct dpp *old_dpp = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.dpp;

			if (old_dpp && !dppclk_active[old_dpp->inst])
				clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, old_dpp->inst, 0);
		}
}

void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
			struct dc_state *context,
			bool safe_to_lower)
{
	union dmub_rb_cmd cmd;
	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
	struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
	struct dc *dc = clk_mgr_base->ctx->dc;
	bool update_dppclk = false;
	bool update_dispclk = false;
	bool dpp_clock_lowered = false;
	bool has_active_display;

	if (dc->work_arounds.skip_clock_update)
		return;

	has_active_display = dcn42_has_active_display(dc, context);

	if (new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz < 590000)
		new_clocks->ref_dtbclk_khz = 600000;
	/*
	 * if it is safe to lower, but we are already in the lower state, we don't have to do anything
	 * also if safe to lower is false, we just go in the higher state
	 */
	if (safe_to_lower) {
		if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
				new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
			dcn42_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
			clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
		}

		if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
			if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk)
				dcn42_smu_set_dtbclk(clk_mgr, false);
			clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
		}
		/* check that we're not already in lower */
		if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
			/* if we can go lower, go lower */
			if (has_active_display == false)
				clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
		}
	} else {
		if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
				new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
			dcn42_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
			clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
		}
		/* Only attempt to enable dtbclk if currently disabled AND new state requests it.
		 * For dcn42b (no dtbclk hardware), init_clk_states sets dtbclk_en=false and
		 * new_clocks->dtbclk_en should always be false, so this block never executes.
		 */
		if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
			int actual_dtbclk = 0;

			dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
			dcn42_smu_set_dtbclk(clk_mgr, true);
			actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk);

			if (actual_dtbclk > 590000) {
				clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;

Annotation

Implementation Notes