brintos

brintos / linux-shallow public Read only

0
0
Text · 25.6 KiB · 51d491b Raw
585 lines · c
1// SPDX-License-Identifier: MIT2//3// Copyright 2024 Advanced Micro Devices, Inc.4 5 6#include "dml2_internal_shared_types.h"7#include "dml21_translation_helper.h"8#include "dml2_internal_types.h"9#include "dml21_utils.h"10#include "dml2_dc_resource_mgmt.h"11 12#include "dml2_core_dcn4_calcs.h"13 14int dml21_helper_find_dml_pipe_idx_by_stream_id(struct dml2_context *ctx, unsigned int stream_id)15{16	int i;17	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {18		if (ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[i] && ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[i] == stream_id)19			return  i;20	}21 22	return -1;23}24 25int dml21_find_dml_pipe_idx_by_plane_id(struct dml2_context *ctx, unsigned int plane_id)26{27	int i;28	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {29		if (ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[i] && ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[i] == plane_id)30			return  i;31	}32 33	return -1;34}35 36bool dml21_get_plane_id(const struct dc_state *state, const struct dc_plane_state *plane, unsigned int *plane_id)37{38	int i, j;39 40	if (!plane_id)41		return false;42 43	for (i = 0; i < state->stream_count; i++) {44		for (j = 0; j < state->stream_status[i].plane_count; j++) {45			if (state->stream_status[i].plane_states[j] == plane) {46				*plane_id = (i << 16) | j;47				return true;48			}49		}50	}51 52	return false;53}54 55unsigned int dml21_get_dc_plane_idx_from_plane_id(unsigned int plane_id)56{57	return 0xffff & plane_id;58}59 60void find_valid_pipe_idx_for_stream_index(const struct dml2_context *dml_ctx, unsigned int *dml_pipe_idx, unsigned int stream_index)61{62	unsigned int i = 0;63 64	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {65		if (dml_ctx->v21.mode_programming.programming->plane_programming[i].plane_descriptor->stream_index == stream_index) {66			*dml_pipe_idx = i;67			return;68		}69	}70}71 72void find_pipe_regs_idx(const struct dml2_context *dml_ctx,73		struct pipe_ctx *pipe, unsigned int *pipe_regs_idx)74{75	struct pipe_ctx *opp_head = dml_ctx->config.callbacks.get_opp_head(pipe);76 77	*pipe_regs_idx = dml_ctx->config.callbacks.get_odm_slice_index(opp_head);78 79	if (pipe->plane_state)80		*pipe_regs_idx += dml_ctx->config.callbacks.get_mpc_slice_index(pipe);81}82 83/* places pipe references into pipes arrays and returns number of pipes */84int dml21_find_dc_pipes_for_plane(const struct dc *in_dc,85		struct dc_state *context,86		struct dml2_context *dml_ctx,87		struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__],88		struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__],89		int dml_plane_idx)90{91	unsigned int dml_stream_index;92	unsigned int main_stream_id;93	unsigned int dc_plane_index;94	struct dc_stream_state *dc_main_stream;95	struct dc_stream_status *dc_main_stream_status;96	struct dc_plane_state *dc_main_plane;97	struct dc_stream_state *dc_phantom_stream;98	struct dc_stream_status *dc_phantom_stream_status;99	struct dc_plane_state *dc_phantom_plane;100	int num_pipes = 0;101 102	memset(dc_main_pipes, 0, sizeof(struct pipe_ctx *) * __DML2_WRAPPER_MAX_STREAMS_PLANES__);103	memset(dc_phantom_pipes, 0, sizeof(struct pipe_ctx *) * __DML2_WRAPPER_MAX_STREAMS_PLANES__);104 105	dml_stream_index = dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_idx].plane_descriptor->stream_index;106	main_stream_id = dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[dml_stream_index];107 108	dc_main_stream = dml_ctx->config.callbacks.get_stream_from_id(context, main_stream_id);109	dc_main_stream_status = dml_ctx->config.callbacks.get_stream_status(context, dc_main_stream);110	if (!dc_main_stream_status)111		return num_pipes;112 113	/* find main plane based on id */114	dc_plane_index = dml21_get_dc_plane_idx_from_plane_id(dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[dml_plane_idx]);115	dc_main_plane = dc_main_stream_status->plane_states[dc_plane_index];116 117	if (dc_main_plane) {118		num_pipes = dml_ctx->config.callbacks.get_dpp_pipes_for_plane(dc_main_plane, &context->res_ctx, dc_main_pipes);119	} else {120		/* stream was configured with dummy plane, so get pipes from opp head */121		struct pipe_ctx *otg_master_pipe = dml_ctx->config.callbacks.get_otg_master_for_stream(&context->res_ctx, dc_main_stream);122		if (otg_master_pipe != NULL)123			num_pipes = dml_ctx->config.callbacks.get_opp_heads_for_otg_master(otg_master_pipe, &context->res_ctx, dc_main_pipes);124	}125 126	/* if phantom exists, find associated pipes */127	dc_phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, dc_main_stream);128	if (dc_phantom_stream && num_pipes > 0) {129		dc_phantom_stream_status = dml_ctx->config.callbacks.get_stream_status(context, dc_phantom_stream);130 131		if (dc_phantom_stream_status) {132			/* phantom plane will have same index as main */133			dc_phantom_plane = dc_phantom_stream_status->plane_states[dc_plane_index];134 135			if (dc_phantom_plane) {136				/* only care about phantom pipes if they contain the phantom plane */137				dml_ctx->config.callbacks.get_dpp_pipes_for_plane(dc_phantom_plane, &context->res_ctx, dc_phantom_pipes);138			}139		}140	}141 142	return num_pipes;143}144 145 146void dml21_update_pipe_ctx_dchub_regs(struct dml2_display_rq_regs *rq_regs,147	struct dml2_display_dlg_regs *disp_dlg_regs,148	struct dml2_display_ttu_regs *disp_ttu_regs,149	struct pipe_ctx *out)150{151	memset(&out->rq_regs, 0, sizeof(out->rq_regs));152	out->rq_regs.rq_regs_l.chunk_size = rq_regs->rq_regs_l.chunk_size;153	out->rq_regs.rq_regs_l.min_chunk_size = rq_regs->rq_regs_l.min_chunk_size;154	//out->rq_regs.rq_regs_l.meta_chunk_size = rq_regs->rq_regs_l.meta_chunk_size;155	//out->rq_regs.rq_regs_l.min_meta_chunk_size = rq_regs->rq_regs_l.min_meta_chunk_size;156	out->rq_regs.rq_regs_l.dpte_group_size = rq_regs->rq_regs_l.dpte_group_size;157	out->rq_regs.rq_regs_l.mpte_group_size = rq_regs->rq_regs_l.mpte_group_size;158	out->rq_regs.rq_regs_l.swath_height = rq_regs->rq_regs_l.swath_height;159	out->rq_regs.rq_regs_l.pte_row_height_linear = rq_regs->rq_regs_l.pte_row_height_linear;160 161	out->rq_regs.rq_regs_c.chunk_size = rq_regs->rq_regs_c.chunk_size;162	out->rq_regs.rq_regs_c.min_chunk_size = rq_regs->rq_regs_c.min_chunk_size;163	//out->rq_regs.rq_regs_c.meta_chunk_size = rq_regs->rq_regs_c.meta_chunk_size;164	//out->rq_regs.rq_regs_c.min_meta_chunk_size = rq_regs->rq_regs_c.min_meta_chunk_size;165	out->rq_regs.rq_regs_c.dpte_group_size = rq_regs->rq_regs_c.dpte_group_size;166	out->rq_regs.rq_regs_c.mpte_group_size = rq_regs->rq_regs_c.mpte_group_size;167	out->rq_regs.rq_regs_c.swath_height = rq_regs->rq_regs_c.swath_height;168	out->rq_regs.rq_regs_c.pte_row_height_linear = rq_regs->rq_regs_c.pte_row_height_linear;169 170	out->rq_regs.drq_expansion_mode = rq_regs->drq_expansion_mode;171	out->rq_regs.prq_expansion_mode = rq_regs->prq_expansion_mode;172	//out->rq_regs.mrq_expansion_mode = rq_regs->mrq_expansion_mode;173	out->rq_regs.crq_expansion_mode = rq_regs->crq_expansion_mode;174	out->rq_regs.plane1_base_address = rq_regs->plane1_base_address;175	out->unbounded_req = rq_regs->unbounded_request_enabled;176 177	memset(&out->dlg_regs, 0, sizeof(out->dlg_regs));178	out->dlg_regs.refcyc_h_blank_end = disp_dlg_regs->refcyc_h_blank_end;179	out->dlg_regs.dlg_vblank_end = disp_dlg_regs->dlg_vblank_end;180	out->dlg_regs.min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start;181	out->dlg_regs.refcyc_per_htotal = disp_dlg_regs->refcyc_per_htotal;182	out->dlg_regs.refcyc_x_after_scaler = disp_dlg_regs->refcyc_x_after_scaler;183	out->dlg_regs.dst_y_after_scaler = disp_dlg_regs->dst_y_after_scaler;184	out->dlg_regs.dst_y_prefetch = disp_dlg_regs->dst_y_prefetch;185	out->dlg_regs.dst_y_per_vm_vblank = disp_dlg_regs->dst_y_per_vm_vblank;186	out->dlg_regs.dst_y_per_row_vblank = disp_dlg_regs->dst_y_per_row_vblank;187	out->dlg_regs.dst_y_per_vm_flip = disp_dlg_regs->dst_y_per_vm_flip;188	out->dlg_regs.dst_y_per_row_flip = disp_dlg_regs->dst_y_per_row_flip;189	out->dlg_regs.ref_freq_to_pix_freq = disp_dlg_regs->ref_freq_to_pix_freq;190	out->dlg_regs.vratio_prefetch = disp_dlg_regs->vratio_prefetch;191	out->dlg_regs.vratio_prefetch_c = disp_dlg_regs->vratio_prefetch_c;192	out->dlg_regs.refcyc_per_tdlut_group = disp_dlg_regs->refcyc_per_tdlut_group;193	out->dlg_regs.refcyc_per_pte_group_vblank_l = disp_dlg_regs->refcyc_per_pte_group_vblank_l;194	out->dlg_regs.refcyc_per_pte_group_vblank_c = disp_dlg_regs->refcyc_per_pte_group_vblank_c;195	//out->dlg_regs.refcyc_per_meta_chunk_vblank_l = disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;196	//out->dlg_regs.refcyc_per_meta_chunk_vblank_c = disp_dlg_regs->refcyc_per_meta_chunk_vblank_c;197	out->dlg_regs.refcyc_per_pte_group_flip_l = disp_dlg_regs->refcyc_per_pte_group_flip_l;198	out->dlg_regs.refcyc_per_pte_group_flip_c = disp_dlg_regs->refcyc_per_pte_group_flip_c;199	//out->dlg_regs.refcyc_per_meta_chunk_flip_l = disp_dlg_regs->refcyc_per_meta_chunk_flip_l;200	//out->dlg_regs.refcyc_per_meta_chunk_flip_c = disp_dlg_regs->refcyc_per_meta_chunk_flip_c;201	out->dlg_regs.dst_y_per_pte_row_nom_l = disp_dlg_regs->dst_y_per_pte_row_nom_l;202	out->dlg_regs.dst_y_per_pte_row_nom_c = disp_dlg_regs->dst_y_per_pte_row_nom_c;203	out->dlg_regs.refcyc_per_pte_group_nom_l = disp_dlg_regs->refcyc_per_pte_group_nom_l;204	out->dlg_regs.refcyc_per_pte_group_nom_c = disp_dlg_regs->refcyc_per_pte_group_nom_c;205	//out->dlg_regs.dst_y_per_meta_row_nom_l = disp_dlg_regs->dst_y_per_meta_row_nom_l;206	//out->dlg_regs.dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_c;207	//out->dlg_regs.refcyc_per_meta_chunk_nom_l = disp_dlg_regs->refcyc_per_meta_chunk_nom_l;208	//out->dlg_regs.refcyc_per_meta_chunk_nom_c = disp_dlg_regs->refcyc_per_meta_chunk_nom_c;209	out->dlg_regs.refcyc_per_line_delivery_pre_l = disp_dlg_regs->refcyc_per_line_delivery_pre_l;210	out->dlg_regs.refcyc_per_line_delivery_pre_c = disp_dlg_regs->refcyc_per_line_delivery_pre_c;211	out->dlg_regs.refcyc_per_line_delivery_l = disp_dlg_regs->refcyc_per_line_delivery_l;212	out->dlg_regs.refcyc_per_line_delivery_c = disp_dlg_regs->refcyc_per_line_delivery_c;213	out->dlg_regs.refcyc_per_vm_group_vblank = disp_dlg_regs->refcyc_per_vm_group_vblank;214	out->dlg_regs.refcyc_per_vm_group_flip = disp_dlg_regs->refcyc_per_vm_group_flip;215	out->dlg_regs.refcyc_per_vm_req_vblank = disp_dlg_regs->refcyc_per_vm_req_vblank;216	out->dlg_regs.refcyc_per_vm_req_flip = disp_dlg_regs->refcyc_per_vm_req_flip;217	out->dlg_regs.dst_y_offset_cur0 = disp_dlg_regs->dst_y_offset_cur0;218	out->dlg_regs.chunk_hdl_adjust_cur0 = disp_dlg_regs->chunk_hdl_adjust_cur0;219	//out->dlg_regs.dst_y_offset_cur1 = disp_dlg_regs->dst_y_offset_cur1;220	//out->dlg_regs.chunk_hdl_adjust_cur1 = disp_dlg_regs->chunk_hdl_adjust_cur1;221	out->dlg_regs.vready_after_vcount0 = disp_dlg_regs->vready_after_vcount0;222	out->dlg_regs.dst_y_delta_drq_limit = disp_dlg_regs->dst_y_delta_drq_limit;223	out->dlg_regs.refcyc_per_vm_dmdata = disp_dlg_regs->refcyc_per_vm_dmdata;224	out->dlg_regs.dmdata_dl_delta = disp_dlg_regs->dmdata_dl_delta;225 226	memset(&out->ttu_regs, 0, sizeof(out->ttu_regs));227	out->ttu_regs.qos_level_low_wm = disp_ttu_regs->qos_level_low_wm;228	out->ttu_regs.qos_level_high_wm = disp_ttu_regs->qos_level_high_wm;229	out->ttu_regs.min_ttu_vblank = disp_ttu_regs->min_ttu_vblank;230	out->ttu_regs.qos_level_flip = disp_ttu_regs->qos_level_flip;231	out->ttu_regs.refcyc_per_req_delivery_l = disp_ttu_regs->refcyc_per_req_delivery_l;232	out->ttu_regs.refcyc_per_req_delivery_c = disp_ttu_regs->refcyc_per_req_delivery_c;233	out->ttu_regs.refcyc_per_req_delivery_cur0 = disp_ttu_regs->refcyc_per_req_delivery_cur0;234	//out->ttu_regs.refcyc_per_req_delivery_cur1 = disp_ttu_regs->refcyc_per_req_delivery_cur1;235	out->ttu_regs.refcyc_per_req_delivery_pre_l = disp_ttu_regs->refcyc_per_req_delivery_pre_l;236	out->ttu_regs.refcyc_per_req_delivery_pre_c = disp_ttu_regs->refcyc_per_req_delivery_pre_c;237	out->ttu_regs.refcyc_per_req_delivery_pre_cur0 = disp_ttu_regs->refcyc_per_req_delivery_pre_cur0;238	//out->ttu_regs.refcyc_per_req_delivery_pre_cur1 = disp_ttu_regs->refcyc_per_req_delivery_pre_cur1;239	out->ttu_regs.qos_level_fixed_l = disp_ttu_regs->qos_level_fixed_l;240	out->ttu_regs.qos_level_fixed_c = disp_ttu_regs->qos_level_fixed_c;241	out->ttu_regs.qos_level_fixed_cur0 = disp_ttu_regs->qos_level_fixed_cur0;242	//out->ttu_regs.qos_level_fixed_cur1 = disp_ttu_regs->qos_level_fixed_cur1;243	out->ttu_regs.qos_ramp_disable_l = disp_ttu_regs->qos_ramp_disable_l;244	out->ttu_regs.qos_ramp_disable_c = disp_ttu_regs->qos_ramp_disable_c;245	out->ttu_regs.qos_ramp_disable_cur0 = disp_ttu_regs->qos_ramp_disable_cur0;246	//out->ttu_regs.qos_ramp_disable_cur1 = disp_ttu_regs->qos_ramp_disable_cur1;247}248 249void dml21_populate_mall_allocation_size(struct dc_state *context,250		struct dml2_context *in_ctx,251		struct dml2_per_plane_programming *pln_prog,252		struct pipe_ctx *dc_pipe)253{254 255	/* Reuse MALL Allocation Sizes logic from dcn32_fpu.c */256	/* Count from active, top pipes per plane only. Only add mall_ss_size_bytes for each unique plane. */257	if (dc_pipe->stream && dc_pipe->plane_state &&258			(dc_pipe->top_pipe == NULL ||259			dc_pipe->plane_state != dc_pipe->top_pipe->plane_state) &&260			dc_pipe->prev_odm_pipe == NULL) {261		/* SS: all active surfaces stored in MALL */262		if (in_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, dc_pipe) != SUBVP_PHANTOM) {263			dc_pipe->surface_size_in_mall_bytes = pln_prog->surface_size_mall_bytes;264			context->bw_ctx.bw.dcn.mall_ss_size_bytes += dc_pipe->surface_size_in_mall_bytes;265		} else {266			/* SUBVP: phantom surfaces only stored in MALL */267			dc_pipe->surface_size_in_mall_bytes = pln_prog->svp_size_mall_bytes;268			context->bw_ctx.bw.dcn.mall_subvp_size_bytes += dc_pipe->surface_size_in_mall_bytes;269		}270	}271}272 273bool check_dp2p0_output_encoder(const struct pipe_ctx *pipe_ctx)274{275	/* If this assert is hit then we have a link encoder dynamic management issue */276	ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);277	return (pipe_ctx->stream_res.hpo_dp_stream_enc &&278		pipe_ctx->link_res.hpo_dp_link_enc &&279		dc_is_dp_signal(pipe_ctx->stream->signal));280}281 282 283static bool is_sub_vp_enabled(struct dc *dc, struct dc_state *context)284{285	int i;286 287	for (i = 0; i < dc->res_pool->pipe_count; i++) {288		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];289 290		if (pipe_ctx->stream && dc_state_get_paired_subvp_stream(context, pipe_ctx->stream) &&291							dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_MAIN) {292			return true;293		}294	}295	return false;296}297 298 299void dml21_program_dc_pipe(struct dml2_context *dml_ctx, struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_plane_programming *pln_prog,300		struct dml2_per_stream_programming *stream_prog)301{302	unsigned int pipe_reg_index = 0;303 304	dml21_populate_pipe_ctx_dlg_params(dml_ctx, context, pipe_ctx, stream_prog);305	find_pipe_regs_idx(dml_ctx, pipe_ctx, &pipe_reg_index);306 307	if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {308		memcpy(&pipe_ctx->hubp_regs, pln_prog->phantom_plane.pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set));309		pipe_ctx->unbounded_req = false;310 311		/* legacy only, should be removed later */312		dml21_update_pipe_ctx_dchub_regs(&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->rq_regs,313				&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->dlg_regs,314				&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->ttu_regs, pipe_ctx);315 316		pipe_ctx->det_buffer_size_kb = 0;317	} else {318		memcpy(&pipe_ctx->hubp_regs, pln_prog->pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set));319		pipe_ctx->unbounded_req = pln_prog->pipe_regs[pipe_reg_index]->rq_regs.unbounded_request_enabled;320 321		/* legacy only, should be removed later */322		dml21_update_pipe_ctx_dchub_regs(&pln_prog->pipe_regs[pipe_reg_index]->rq_regs,323				&pln_prog->pipe_regs[pipe_reg_index]->dlg_regs,324				&pln_prog->pipe_regs[pipe_reg_index]->ttu_regs, pipe_ctx);325 326		pipe_ctx->det_buffer_size_kb = pln_prog->pipe_regs[pipe_reg_index]->det_size * 64;327	}328 329	pipe_ctx->plane_res.bw.dppclk_khz = pln_prog->min_clocks.dcn4x.dppclk_khz;330	if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipe_ctx->plane_res.bw.dppclk_khz)331		context->bw_ctx.bw.dcn.clk.dppclk_khz = pipe_ctx->plane_res.bw.dppclk_khz;332 333	dml21_populate_mall_allocation_size(context, dml_ctx, pln_prog, pipe_ctx);334	memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[pipe_ctx->pipe_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation));335 336	bool sub_vp_enabled = is_sub_vp_enabled(pipe_ctx->stream->ctx->dc, context);337 338	dml21_set_dc_p_state_type(pipe_ctx, stream_prog, sub_vp_enabled);339}340 341static struct dc_stream_state *dml21_add_phantom_stream(struct dml2_context *dml_ctx,342	const struct dc *dc,343	struct dc_state *context,344	struct dc_stream_state *main_stream,345	struct dml2_per_stream_programming *stream_programming)346{347	struct dc_stream_state *phantom_stream;348	struct dml2_stream_parameters *phantom_stream_descriptor = &stream_programming->phantom_stream.descriptor;349 350	phantom_stream = dml_ctx->config.svp_pstate.callbacks.create_phantom_stream(dc, context, main_stream);351	if (!phantom_stream)352		return NULL;353 354	/* copy details of phantom stream from main */355	memcpy(&phantom_stream->timing, &main_stream->timing, sizeof(phantom_stream->timing));356	memcpy(&phantom_stream->src, &main_stream->src, sizeof(phantom_stream->src));357	memcpy(&phantom_stream->dst, &main_stream->dst, sizeof(phantom_stream->dst));358 359	/* modify timing for phantom */360	phantom_stream->timing.v_front_porch = phantom_stream_descriptor->timing.v_front_porch;361	phantom_stream->timing.v_addressable = phantom_stream_descriptor->timing.v_active;362	phantom_stream->timing.v_total = phantom_stream_descriptor->timing.v_total;363	phantom_stream->timing.flags.DSC = 0; // phantom always has DSC disabled364 365	phantom_stream->dst.y = 0;366	phantom_stream->dst.height = stream_programming->phantom_stream.descriptor.timing.v_active;367 368	phantom_stream->src.y = 0;369	phantom_stream->src.height = (double)phantom_stream_descriptor->timing.v_active * (double)main_stream->src.height / (double)main_stream->dst.height;370 371	phantom_stream->use_dynamic_meta = false;372 373	dml_ctx->config.svp_pstate.callbacks.add_phantom_stream(dc, context, phantom_stream, main_stream);374 375	return phantom_stream;376}377 378static struct dc_plane_state *dml21_add_phantom_plane(struct dml2_context *dml_ctx,379	const struct dc *dc,380	struct dc_state *context,381	struct dc_stream_state *phantom_stream,382	struct dc_plane_state *main_plane,383	struct dml2_per_plane_programming *plane_programming)384{385	struct dc_plane_state *phantom_plane;386 387	phantom_plane = dml_ctx->config.svp_pstate.callbacks.create_phantom_plane(dc, context, main_plane);388	if (!phantom_plane)389		return NULL;390 391	phantom_plane->format = main_plane->format;392	phantom_plane->rotation = main_plane->rotation;393	phantom_plane->visible = main_plane->visible;394 395	memcpy(&phantom_plane->address, &main_plane->address, sizeof(phantom_plane->address));396	memcpy(&phantom_plane->scaling_quality, &main_plane->scaling_quality,397		sizeof(phantom_plane->scaling_quality));398	memcpy(&phantom_plane->src_rect, &main_plane->src_rect, sizeof(phantom_plane->src_rect));399	memcpy(&phantom_plane->dst_rect, &main_plane->dst_rect, sizeof(phantom_plane->dst_rect));400	memcpy(&phantom_plane->clip_rect, &main_plane->clip_rect, sizeof(phantom_plane->clip_rect));401	memcpy(&phantom_plane->plane_size, &main_plane->plane_size,402		sizeof(phantom_plane->plane_size));403	memcpy(&phantom_plane->tiling_info, &main_plane->tiling_info,404		sizeof(phantom_plane->tiling_info));405	memcpy(&phantom_plane->dcc, &main_plane->dcc, sizeof(phantom_plane->dcc));406 407	phantom_plane->format = main_plane->format;408	phantom_plane->rotation = main_plane->rotation;409	phantom_plane->visible = main_plane->visible;410 411	/* Shadow pipe has small viewport. */412	phantom_plane->clip_rect.y = 0;413	phantom_plane->clip_rect.height = phantom_stream->src.height;414 415	dml_ctx->config.svp_pstate.callbacks.add_phantom_plane(dc, phantom_stream, phantom_plane, context);416 417	return phantom_plane;418}419 420void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *context, struct dml2_context *dml_ctx)421{422	unsigned int dml_stream_index, dml_plane_index, dc_plane_index;423	struct dc_stream_state *main_stream;424	struct dc_stream_status *main_stream_status;425	struct dc_stream_state *phantom_stream;426	struct dc_plane_state *main_plane;427	bool phantoms_added = false;428 429	/* create phantom streams and planes and add to context */430	for (dml_stream_index = 0; dml_stream_index < dml_ctx->v21.mode_programming.programming->display_config.num_streams; dml_stream_index++) {431		/* iterate through DML streams looking for phantoms */432		if (dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_index].phantom_stream.enabled) {433			/* find associated dc stream */434			main_stream = dml_ctx->config.callbacks.get_stream_from_id(context,435					dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[dml_stream_index]);436 437			main_stream_status = dml_ctx->config.callbacks.get_stream_status(context, main_stream);438 439			if (!main_stream_status || main_stream_status->plane_count == 0)440				continue;441 442			/* create phantom stream for subvp enabled stream */443			phantom_stream = dml21_add_phantom_stream(dml_ctx,444					dc,445					context,446					main_stream,447					&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_index]);448 449			if (!phantom_stream)450				continue;451 452			/* iterate through DML planes associated with this stream */453			for (dml_plane_index = 0; dml_plane_index < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_plane_index++) {454				if (dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_index].plane_descriptor->stream_index == dml_stream_index) {455					/* find associated dc plane */456					dc_plane_index = dml21_get_dc_plane_idx_from_plane_id(dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[dml_plane_index]);457					main_plane = main_stream_status->plane_states[dc_plane_index];458 459					/* create phantom planes for subvp enabled plane */460					dml21_add_phantom_plane(dml_ctx,461							dc,462							context,463							phantom_stream,464							main_plane,465							&dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_index]);466 467					phantoms_added = true;468				}469			}470		}471	}472 473	if (phantoms_added)474		dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state);475}476 477void dml21_build_fams2_programming(const struct dc *dc,478		struct dc_state *context,479		struct dml2_context *dml_ctx)480{481	int i, j, k;482	unsigned int num_fams2_streams = 0;483 484	/* reset fams2 data */485	memset(&context->bw_ctx.bw.dcn.fams2_stream_params, 0, sizeof(struct dmub_fams2_stream_static_state) * DML2_MAX_PLANES);486	memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config));487 488	if (dml_ctx->v21.mode_programming.programming->fams2_required) {489		for (i = 0; i < context->stream_count; i++) {490			int dml_stream_idx;491			struct dc_stream_state *phantom_stream;492			struct dc_stream_status *phantom_status;493 494			struct dmub_fams2_stream_static_state *static_state = &context->bw_ctx.bw.dcn.fams2_stream_params[num_fams2_streams];495 496			struct dc_stream_state *stream = context->streams[i];497 498			if (context->stream_status[i].plane_count == 0 ||499					dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) {500				/* can ignore blanked or phantom streams */501				continue;502			}503 504			dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id);505			if (dml_stream_idx < 0) {506				ASSERT(dml_stream_idx >= 0);507				continue;508			}509 510			/* copy static state from PMO */511			memcpy(static_state,512					&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_params,513					sizeof(struct dmub_fams2_stream_static_state));514 515			/* get information from context */516			static_state->num_planes = context->stream_status[i].plane_count;517			static_state->otg_inst = context->stream_status[i].primary_otg_inst;518 519			/* populate pipe masks for planes */520			for (j = 0; j < context->stream_status[i].plane_count; j++) {521				for (k = 0; k < dc->res_pool->pipe_count; k++) {522					if (context->res_ctx.pipe_ctx[k].stream &&523							context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id &&524							context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) {525						static_state->pipe_mask |= (1 << k);526						static_state->plane_pipe_masks[j] |= (1 << k);527					}528				}529			}530 531			/* get per method programming */532			switch (static_state->type) {533			case FAMS2_STREAM_TYPE_VBLANK:534			case FAMS2_STREAM_TYPE_VACTIVE:535			case FAMS2_STREAM_TYPE_DRR:536				break;537			case FAMS2_STREAM_TYPE_SUBVP:538				phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream);539				if (!phantom_stream)540					break;541 542				phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream);543 544				/* phantom status should always be present */545				ASSERT(phantom_status);546				static_state->sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst;547 548				/* populate pipe masks for phantom planes */549				for (j = 0; j < phantom_status->plane_count; j++) {550					for (k = 0; k < dc->res_pool->pipe_count; k++) {551						if (context->res_ctx.pipe_ctx[k].stream &&552								context->res_ctx.pipe_ctx[k].stream->stream_id == phantom_stream->stream_id &&553								context->res_ctx.pipe_ctx[k].plane_state == phantom_status->plane_states[j]) {554							static_state->sub_state.subvp.phantom_pipe_mask |= (1 << k);555							static_state->sub_state.subvp.phantom_plane_pipe_masks[j] |= (1 << k);556						}557					}558				}559				break;560			default:561				ASSERT(false);562				break;563			}564 565			num_fams2_streams++;566		}567	}568 569	if (num_fams2_streams > 0) {570		/* copy FAMS2 configuration */571		memcpy(&context->bw_ctx.bw.dcn.fams2_global_config,572				&dml_ctx->v21.mode_programming.programming->fams2_global_config,573				sizeof(struct dmub_cmd_fams2_global_config));574 575		context->bw_ctx.bw.dcn.fams2_global_config.num_streams = num_fams2_streams;576	}577 578	context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;579}580 581bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format)582{583	return source_format >= dml2_420_8 && source_format <= dml2_rgbe_alpha;584}585