File Index
Files and directories
Sign in
FILE

dml21_utils.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c C
  1// SPDX-License-Identifier: MIT
  2//
  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
145void dml21_pipe_populate_global_sync(struct dml2_context *dml_ctx,
146	struct dc_state *context,
147	struct pipe_ctx *pipe_ctx,
148	struct dml2_per_stream_programming *stream_programming)
149{
150	union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
151
152	if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
153		/* phantom has its own global sync */
154		global_sync = &stream_programming->phantom_stream.global_sync;
155	}
156
157	memcpy(&pipe_ctx->global_sync,
158		global_sync,
159		sizeof(union dml2_global_sync_programming));
160}
161
162void dml21_populate_mall_allocation_size(struct dc_state *context,
163		struct dml2_context *in_ctx,
164		struct dml2_per_plane_programming *pln_prog,
165		struct pipe_ctx *dc_pipe)
166{
167
168	/* Reuse MALL Allocation Sizes logic from dcn32_fpu.c */
169	/* Count from active, top pipes per plane only. Only add mall_ss_size_bytes for each unique plane. */
170	if (dc_pipe->stream && dc_pipe->plane_state &&
171			(dc_pipe->top_pipe == NULL ||
172			dc_pipe->plane_state != dc_pipe->top_pipe->plane_state) &&
173			dc_pipe->prev_odm_pipe == NULL) {
174		/* SS: all active surfaces stored in MALL */
175		if (in_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, dc_pipe) != SUBVP_PHANTOM) {
176			dc_pipe->surface_size_in_mall_bytes = pln_prog->surface_size_mall_bytes;
177			context->bw_ctx.bw.dcn.mall_ss_size_bytes += dc_pipe->surface_size_in_mall_bytes;
178		} else {
179			/* SUBVP: phantom surfaces only stored in MALL */
180			dc_pipe->surface_size_in_mall_bytes = pln_prog->svp_size_mall_bytes;
181			context->bw_ctx.bw.dcn.mall_subvp_size_bytes += dc_pipe->surface_size_in_mall_bytes;
182		}
183	}
184}
185
186bool check_dp2p0_output_encoder(const struct pipe_ctx *pipe_ctx)
187{
188	/* If this assert is hit then we have a link encoder dynamic management issue */
189	ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);
190	return (pipe_ctx->stream_res.hpo_dp_stream_enc &&
191		pipe_ctx->link_res.hpo_dp_link_enc &&
192		dc_is_dp_signal(pipe_ctx->stream->signal));
193}
194
195
196static bool is_sub_vp_enabled(struct dc *dc, struct dc_state *context)
197{
198	int i;
199
200	for (i = 0; i < dc->res_pool->pipe_count; i++) {
201		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
202
203		if (pipe_ctx->stream && dc_state_get_paired_subvp_stream(context, pipe_ctx->stream) &&
204							dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_MAIN) {
205			return true;
206		}
207	}
208	return false;
209}
210
211
212void 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,
213		struct dml2_per_stream_programming *stream_prog)
214{
215	unsigned int pipe_reg_index = 0;
216
217	dml21_pipe_populate_global_sync(dml_ctx, context, pipe_ctx, stream_prog);
218	find_pipe_regs_idx(dml_ctx, pipe_ctx, &pipe_reg_index);
219
220	if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
221		memcpy(&pipe_ctx->hubp_regs, pln_prog->phantom_plane.pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set));
222		pipe_ctx->unbounded_req = false;
223		pipe_ctx->det_buffer_size_kb = 0;
224	} else {
225		memcpy(&pipe_ctx->hubp_regs, pln_prog->pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set));
226		pipe_ctx->unbounded_req = pln_prog->pipe_regs[pipe_reg_index]->rq_regs.unbounded_request_enabled;
227		pipe_ctx->det_buffer_size_kb = pln_prog->pipe_regs[pipe_reg_index]->det_size * 64;
228	}
229
230	pipe_ctx->plane_res.bw.dppclk_khz = pln_prog->min_clocks.dcn4x.dppclk_khz;
231	if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipe_ctx->plane_res.bw.dppclk_khz)
232		context->bw_ctx.bw.dcn.clk.dppclk_khz = pipe_ctx->plane_res.bw.dppclk_khz;
233
234	dml21_populate_mall_allocation_size(context, dml_ctx, pln_prog, pipe_ctx);
235
236	bool sub_vp_enabled = is_sub_vp_enabled(pipe_ctx->stream->ctx->dc, context);
237
238	dml21_set_dc_p_state_type(pipe_ctx, stream_prog, sub_vp_enabled);
239}
240
241static struct dc_stream_state *dml21_add_phantom_stream(struct dml2_context *dml_ctx,
242	const struct dc *dc,
243	struct dc_state *context,
244	struct dc_stream_state *main_stream,
245	struct dml2_per_stream_programming *stream_programming)
246{
247	struct dc_stream_state *phantom_stream;
248	struct dml2_stream_parameters *phantom_stream_descriptor = &stream_programming->phantom_stream.descriptor;
249
250	phantom_stream = dml_ctx->config.svp_pstate.callbacks.create_phantom_stream(dc, context, main_stream);
251	if (!phantom_stream)
252		return NULL;
253
254	/* copy details of phantom stream from main */
255	memcpy(&phantom_stream->timing, &main_stream->timing, sizeof(phantom_stream->timing));
256	memcpy(&phantom_stream->src, &main_stream->src, sizeof(phantom_stream->src));
257	memcpy(&phantom_stream->dst, &main_stream->dst, sizeof(phantom_stream->dst));
258
259	/* modify timing for phantom */
260	phantom_stream->timing.v_front_porch = phantom_stream_descriptor->timing.v_front_porch;
261	phantom_stream->timing.v_addressable = phantom_stream_descriptor->timing.v_active;
262	phantom_stream->timing.v_total = phantom_stream_descriptor->timing.v_total;
263	phantom_stream->timing.flags.DSC = 0; // phantom always has DSC disabled
264
265	phantom_stream->dst.y = 0;
266	phantom_stream->dst.height = stream_programming->phantom_stream.descriptor.timing.v_active;
267
268	phantom_stream->src.y = 0;
269	phantom_stream->src.height = (double)phantom_stream_descriptor->timing.v_active * (double)main_stream->src.height / (double)main_stream->dst.height;
270
271	phantom_stream->use_dynamic_meta = false;
272
273	dml_ctx->config.svp_pstate.callbacks.add_phantom_stream(dc, context, phantom_stream, main_stream);
274
275	return phantom_stream;
276}
277
278static struct dc_plane_state *dml21_add_phantom_plane(struct dml2_context *dml_ctx,
279	const struct dc *dc,
280	struct dc_state *context,
281	struct dc_stream_state *phantom_stream,
282	struct dc_plane_state *main_plane,
283	struct dml2_per_plane_programming *plane_programming)
284{
285	struct dc_plane_state *phantom_plane;
286
287	phantom_plane = dml_ctx->config.svp_pstate.callbacks.create_phantom_plane(dc, context, main_plane);
288	if (!phantom_plane)
289		return NULL;
290
291	phantom_plane->format = main_plane->format;
292	phantom_plane->rotation = main_plane->rotation;
293	phantom_plane->visible = main_plane->visible;
294
295	memcpy(&phantom_plane->address, &main_plane->address, sizeof(phantom_plane->address));
296	memcpy(&phantom_plane->scaling_quality, &main_plane->scaling_quality,
297		sizeof(phantom_plane->scaling_quality));
298	memcpy(&phantom_plane->src_rect, &main_plane->src_rect, sizeof(phantom_plane->src_rect));
299	memcpy(&phantom_plane->dst_rect, &main_plane->dst_rect, sizeof(phantom_plane->dst_rect));
300	memcpy(&phantom_plane->clip_rect, &main_plane->clip_rect, sizeof(phantom_plane->clip_rect));
301	memcpy(&phantom_plane->plane_size, &main_plane->plane_size,
302		sizeof(phantom_plane->plane_size));
303	memcpy(&phantom_plane->tiling_info, &main_plane->tiling_info,
304		sizeof(phantom_plane->tiling_info));
305	memcpy(&phantom_plane->dcc, &main_plane->dcc, sizeof(phantom_plane->dcc));
306
307	phantom_plane->format = main_plane->format;
308	phantom_plane->rotation = main_plane->rotation;
309	phantom_plane->visible = main_plane->visible;
310
311	/* Shadow pipe has small viewport. */
312	phantom_plane->clip_rect.y = 0;
313	phantom_plane->clip_rect.height = phantom_stream->src.height;
314
315	dml_ctx->config.svp_pstate.callbacks.add_phantom_plane(dc, phantom_stream, phantom_plane, context);
316
317	return phantom_plane;
318}
319
320void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *context, struct dml2_context *dml_ctx)
321{
322	unsigned int dml_stream_index, dml_plane_index, dc_plane_index;
323	struct dc_stream_state *main_stream;
324	struct dc_stream_status *main_stream_status;
325	struct dc_stream_state *phantom_stream;
326	struct dc_plane_state *main_plane;
327	bool phantoms_added = false;
328
329	/* create phantom streams and planes and add to context */
330	for (dml_stream_index = 0; dml_stream_index < dml_ctx->v21.mode_programming.programming->display_config.num_streams; dml_stream_index++) {
331		/* iterate through DML streams looking for phantoms */
332		if (dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_index].phantom_stream.enabled) {
333			/* find associated dc stream */
334			main_stream = dml_ctx->config.callbacks.get_stream_from_id(context,
335					dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[dml_stream_index]);
336
337			main_stream_status = dml_ctx->config.callbacks.get_stream_status(context, main_stream);
338
339			if (!main_stream_status || main_stream_status->plane_count == 0)
340				continue;
341
342			/* create phantom stream for subvp enabled stream */
343			phantom_stream = dml21_add_phantom_stream(dml_ctx,
344					dc,
345					context,
346					main_stream,
347					&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_index]);
348
349			if (!phantom_stream)
350				continue;
351
352			/* iterate through DML planes associated with this stream */
353			for (dml_plane_index = 0; dml_plane_index < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_plane_index++) {
354				if (dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_index].plane_descriptor->stream_index == dml_stream_index) {
355					/* find associated dc plane */
356					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]);
357					main_plane = main_stream_status->plane_states[dc_plane_index];
358
359					/* create phantom planes for subvp enabled plane */
360					dml21_add_phantom_plane(dml_ctx,
361							dc,
362							context,
363							phantom_stream,
364							main_plane,
365							&dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_index]);
366
367					phantoms_added = true;
368				}
369			}
370		}
371	}
372
373	if (phantoms_added)
374		dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state);
375}
376
377void dml21_build_fams2_programming(const struct dc *dc,
378		struct dc_state *context,
379		struct dml2_context *dml_ctx)
380{
381	int i, j, k;
382	unsigned int num_fams2_streams = 0;
383
384	/* reset fams2 data */
385	memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES);
386	memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES);
387	memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES);
388	memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config));
389
390	if (dml_ctx->v21.mode_programming.programming->fams2_required) {
391		for (i = 0; i < context->stream_count; i++) {
392			int dml_stream_idx;
393			struct dc_stream_state *phantom_stream;
394			struct dc_stream_status *phantom_status;
395			enum fams2_stream_type type = 0;
396
397			union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams];
398			union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams];
399
400			struct dc_stream_state *stream = context->streams[i];
401
402			if (context->stream_status[i].plane_count == 0 ||
403					dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) {
404				/* can ignore blanked or phantom streams */
405				continue;
406			}
407
408			dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id);
409			if (dml_stream_idx < 0) {
410				ASSERT(dml_stream_idx >= 0);
411				continue;
412			}
413
414			/* copy static state from PMO */
415			memcpy(static_base_state,
416					&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params,
417					sizeof(union dmub_cmd_fams2_config));
418
419			if (dc->debug.fams_version.major == 3) {
420				memcpy(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams],
421						&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params_v2,
422						sizeof(union dmub_fams2_stream_static_sub_state_v2));
423			} else {
424				memcpy(static_sub_state,
425						&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params,
426						sizeof(union dmub_cmd_fams2_config));
427			}
428
429			switch (dc->debug.fams_version.minor) {
430			case 1:
431			default:
432				type = static_base_state->stream_v1.base.type;
433
434				/* get information from context */
435				static_base_state->stream_v1.base.num_planes = context->stream_status[i].plane_count;
436				static_base_state->stream_v1.base.otg_inst = context->stream_status[i].primary_otg_inst;
437
438				/* populate pipe masks for planes */
439				for (j = 0; j < context->stream_status[i].plane_count; j++) {
440					for (k = 0; k < dc->res_pool->pipe_count; k++) {
441						if (context->res_ctx.pipe_ctx[k].stream &&
442								context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id &&
443								context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) {
444							static_base_state->stream_v1.base.pipe_mask |= (1 << k);
445							static_base_state->stream_v1.base.plane_pipe_masks[j] |= (1 << k);
446						}
447					}
448				}
449			}
450
451
452			/* get per method programming */
453			switch (type) {
454			case FAMS2_STREAM_TYPE_VBLANK:
455			case FAMS2_STREAM_TYPE_VACTIVE:
456			case FAMS2_STREAM_TYPE_DRR:
457				break;
458			case FAMS2_STREAM_TYPE_SUBVP:
459				phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream);
460				if (!phantom_stream)
461					break;
462
463				phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream);
464
465				/* phantom status should always be present */
466				ASSERT(phantom_status);
467				if (!phantom_status)
468					break;
469
470				switch (dc->debug.fams_version.minor) {
471				case 1:
472				default:
473					static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst;
474
475					/* populate pipe masks for phantom planes */
476					for (j = 0; j < phantom_status->plane_count; j++) {
477						for (k = 0; k < dc->res_pool->pipe_count; k++) {
478							if (context->res_ctx.pipe_ctx[k].stream &&
479									context->res_ctx.pipe_ctx[k].stream->stream_id == phantom_stream->stream_id &&
480									context->res_ctx.pipe_ctx[k].plane_state == phantom_status->plane_states[j]) {
481								switch (dc->debug.fams_version.minor) {
482								case 1:
483								default:
484									static_sub_state->stream_v1.sub_state.subvp.phantom_pipe_mask |= (1 << k);
485									static_sub_state->stream_v1.sub_state.subvp.phantom_plane_pipe_masks[j] |= (1 << k);
486								}
487							}
488						}
489					}
490				}
491				break;
492			default:
493				ASSERT(false);
494				break;
495			}
496
497			num_fams2_streams++;
498		}
499	}
500
501	if (num_fams2_streams > 0) {
502		/* copy FAMS2 configuration */
503		memcpy(&context->bw_ctx.bw.dcn.fams2_global_config,
504				&dml_ctx->v21.mode_programming.programming->fams2_global_config,
505				sizeof(struct dmub_cmd_fams2_global_config));
506
507		context->bw_ctx.bw.dcn.fams2_global_config.num_streams = num_fams2_streams;
508	}
509
510	context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
511}
512
513bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format)
514{
515	return source_format >= dml2_420_8 && source_format <= dml2_rgbe_alpha;
516}
~/ Read-only file preview.