drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c
Extension
.c
Size
28645 bytes
Lines
565
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 (state->streams[i]->stream_id == stream_id) {
			for (j = 0; j < state->stream_status[i].plane_count; j++) {
				if (state->stream_status[i].plane_states[j] == plane &&
					(!is_plane_duplicate || (j == plane_index))) {
					*plane_id = (i << 16) | j;
					return true;
				}
			}
		}
	}

	return false;
}

static void populate_pipe_ctx_dlg_params_from_dml(struct pipe_ctx *pipe_ctx, struct display_mode_lib_st *mode_lib, dml_uint_t pipe_idx)
{
	unsigned int hactive, vactive, hblank_start, vblank_start, hblank_end, vblank_end;
	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;

	hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right;
	vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top;
	hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch;
	vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch;

	hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right;
	vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;

	pipe_ctx->pipe_dlg_param.vstartup_start = dml_get_vstartup_calculated(mode_lib,	pipe_idx);
	pipe_ctx->pipe_dlg_param.vupdate_offset = dml_get_vupdate_offset(mode_lib, pipe_idx);
	pipe_ctx->pipe_dlg_param.vupdate_width = dml_get_vupdate_width(mode_lib, pipe_idx);
	pipe_ctx->pipe_dlg_param.vready_offset = dml_get_vready_offset(mode_lib, pipe_idx);

	ASSERT(pipe_ctx->stream_res.tg->inst <= 0xFF);
	pipe_ctx->pipe_dlg_param.otg_inst = (unsigned char)pipe_ctx->stream_res.tg->inst;

	pipe_ctx->pipe_dlg_param.hactive = hactive;
	pipe_ctx->pipe_dlg_param.vactive = vactive;
	pipe_ctx->pipe_dlg_param.htotal = pipe_ctx->stream->timing.h_total;
	pipe_ctx->pipe_dlg_param.vtotal = pipe_ctx->stream->timing.v_total;
	pipe_ctx->pipe_dlg_param.hblank_end = hblank_end;
	pipe_ctx->pipe_dlg_param.vblank_end = vblank_end;
	pipe_ctx->pipe_dlg_param.hblank_start = hblank_start;
	pipe_ctx->pipe_dlg_param.vblank_start = vblank_start;
	pipe_ctx->pipe_dlg_param.vfront_porch = pipe_ctx->stream->timing.v_front_porch;
	pipe_ctx->pipe_dlg_param.pixel_rate_mhz = pipe_ctx->stream->timing.pix_clk_100hz / 10000.00;
	pipe_ctx->pipe_dlg_param.refresh_rate = ((timing->pix_clk_100hz * 100) / timing->h_total) / timing->v_total;
	pipe_ctx->pipe_dlg_param.vtotal_max = pipe_ctx->stream->adjust.v_total_max;
	pipe_ctx->pipe_dlg_param.vtotal_min = pipe_ctx->stream->adjust.v_total_min;
	pipe_ctx->pipe_dlg_param.recout_height = pipe_ctx->plane_res.scl_data.recout.height;
	pipe_ctx->pipe_dlg_param.recout_width = pipe_ctx->plane_res.scl_data.recout.width;
	pipe_ctx->pipe_dlg_param.full_recout_height = pipe_ctx->plane_res.scl_data.recout.height;
	pipe_ctx->pipe_dlg_param.full_recout_width = pipe_ctx->plane_res.scl_data.recout.width;
}

void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state, struct dml2_context *in_ctx, unsigned int pipe_cnt)
{
	unsigned int dc_pipe_ctx_index, dml_pipe_idx, plane_id;
	enum mall_stream_type pipe_mall_type;
	struct dml2_calculate_rq_and_dlg_params_scratch *s = &in_ctx->v20.scratch.calculate_rq_and_dlg_params_scratch;

	context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = (unsigned int)in_ctx->v20.dml_core_ctx.mp.DCFCLKDeepSleep * 1000;
	context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;

	if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[0] == dml_fclock_change_unsupported)
		context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false;
	else
		context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true;

	if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz)
		context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz;

	context->bw_ctx.bw.dcn.compbuf_size_kb = in_ctx->v20.dml_core_ctx.ip.config_return_buffer_size_in_kbytes;

	for (dc_pipe_ctx_index = 0; dc_pipe_ctx_index < pipe_cnt; dc_pipe_ctx_index++) {
		if (!context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream)
			continue;
		/* The DML2 and the DC logic of determining pipe indices are different from each other so
		 * there is a need to know which DML pipe index maps to which DC pipe. The code below
		 * finds a dml_pipe_index from the plane id if a plane is valid. If a plane is not valid then
		 * it finds a dml_pipe_index from the stream id. */
		if (get_plane_id(in_ctx, context, context->res_ctx.pipe_ctx[dc_pipe_ctx_index].plane_state,
			context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id,
			in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[context->res_ctx.pipe_ctx[dc_pipe_ctx_index].pipe_idx], &plane_id)) {
			dml_pipe_idx = find_dml_pipe_idx_by_plane_id(in_ctx, plane_id);
		} else {
			dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(in_ctx, context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id);
		}

		if (dml_pipe_idx == 0xFFFFFFFF)
			continue;

Annotation

Implementation Notes