File Index
Files and directories
Sign in
FILE

dml21_translation_helper.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c C
  1// SPDX-License-Identifier: MIT
  2//
  3// Copyright 2024 Advanced Micro Devices, Inc.
  4
  5#include "dml21_wrapper.h"
  6#include "dml2_core_dcn4_calcs.h"
  7#include "dml2_internal_shared_types.h"
  8#include "dml2_internal_types.h"
  9#include "dml21_utils.h"
 10#include "dml21_translation_helper.h"
 11#include "soc_and_ip_translator.h"
 12
 13static void dml21_populate_pmo_options(struct dml2_pmo_options *pmo_options,
 14		const struct dc *in_dc,
 15		const struct dml2_configuration_options *config)
 16{
 17	bool disable_fams2 = !in_dc->debug.fams2_config.bits.enable;
 18
 19	/* ODM options */
 20	pmo_options->disable_dyn_odm = !config->minimize_dispclk_using_odm;
 21	pmo_options->disable_dyn_odm_for_multi_stream = true;
 22	pmo_options->disable_dyn_odm_for_stream_with_svp = true;
 23
 24	pmo_options->disable_vblank = ((in_dc->debug.dml21_disable_pstate_method_mask >> 1) & 1);
 25
 26	/* NOTE: DRR and SubVP Require FAMS2 */
 27	pmo_options->disable_svp = ((in_dc->debug.dml21_disable_pstate_method_mask >> 2) & 1) ||
 28			in_dc->debug.force_disable_subvp ||
 29			disable_fams2;
 30	pmo_options->disable_drr_clamped = ((in_dc->debug.dml21_disable_pstate_method_mask >> 3) & 1) ||
 31			disable_fams2;
 32	pmo_options->disable_drr_var = ((in_dc->debug.dml21_disable_pstate_method_mask >> 4) & 1) ||
 33			disable_fams2;
 34	pmo_options->disable_fams2 = disable_fams2;
 35
 36	pmo_options->disable_drr_var_when_var_active = in_dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE ||
 37			in_dc->debug.disable_fams_gaming == INGAME_FAMS_MULTI_DISP_CLAMPED_ONLY;
 38	pmo_options->disable_drr_clamped_when_var_active = in_dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE;
 39}
 40
 41static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_version dcn_version)
 42{
 43	enum dml2_project_id project_id;
 44	switch (dcn_version) {
 45	case DCN_VERSION_4_01:
 46		project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
 47		break;
 48	default:
 49		project_id = dml2_project_invalid;
 50		DC_ERR("unsupported dcn version for DML21!");
 51		break;
 52	}
 53
 54	return project_id;
 55}
 56
 57void dml21_populate_dml_init_params(struct dml2_initialize_instance_in_out *dml_init,
 58		const struct dml2_configuration_options *config,
 59		const struct dc *in_dc)
 60{
 61	dml_init->options.project_id = dml21_dcn_revision_to_dml2_project_id(in_dc->ctx->dce_version);
 62
 63	if (config->use_native_soc_bb_construction) {
 64		in_dc->soc_and_ip_translator->translator_funcs->get_soc_bb(&dml_init->soc_bb, in_dc, config);
 65		in_dc->soc_and_ip_translator->translator_funcs->get_ip_caps(&dml_init->ip_caps);
 66	} else {
 67		dml_init->soc_bb = config->external_socbb_ip_params->soc_bb;
 68		dml_init->ip_caps = config->external_socbb_ip_params->ip_params;
 69	}
 70
 71	dml21_populate_pmo_options(&dml_init->options.pmo_options, in_dc, config);
 72}
 73
 74static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
 75{
 76	unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
 77
 78	if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
 79		max_hw_v_total -= stream->timing.v_front_porch + 1;
 80	}
 81
 82	return max_hw_v_total;
 83}
 84
 85static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg *timing,
 86		struct dc_stream_state *stream,
 87		struct pipe_ctx *pipe_ctx,
 88		struct dml2_context *dml_ctx)
 89{
 90	unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz;
 91	uint32_t pix_clk_100hz;
 92
 93	timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->dsc_padding_params.dsc_hactive_padding;
 94	timing->v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
 95	timing->h_front_porch = stream->timing.h_front_porch;
 96	timing->v_front_porch = stream->timing.v_front_porch;
 97	timing->pixel_clock_khz = stream->timing.pix_clk_100hz / 10;
 98	if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0)
 99		timing->pixel_clock_khz = pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz / 10;
100	if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
101		timing->pixel_clock_khz *= 2;
102	timing->h_total = stream->timing.h_total + pipe_ctx->dsc_padding_params.dsc_htotal_padding;
103	timing->v_total = stream->timing.v_total;
104	timing->h_sync_width = stream->timing.h_sync_width;
105	timing->interlaced = stream->timing.flags.INTERLACE;
106
107	hblank_start = stream->timing.h_total - stream->timing.h_front_porch;
108
109	timing->h_blank_end = hblank_start - stream->timing.h_addressable - pipe_ctx->dsc_padding_params.dsc_hactive_padding
110		- stream->timing.h_border_left - stream->timing.h_border_right;
111
112	if (hblank_start < stream->timing.h_addressable)
113		timing->h_blank_end = 0;
114
115	vblank_start = stream->timing.v_total - stream->timing.v_front_porch;
116
117	timing->v_blank_end = vblank_start - stream->timing.v_addressable
118		- stream->timing.v_border_top - stream->timing.v_border_bottom;
119
120	timing->drr_config.enabled = stream->ignore_msa_timing_param;
121	timing->drr_config.drr_active_variable = stream->vrr_active_variable;
122	timing->drr_config.drr_active_fixed = stream->vrr_active_fixed;
123	timing->drr_config.disallowed = !stream->allow_freesync;
124
125	/* limit min refresh rate to DC cap */
126	min_hardware_refresh_in_uhz = stream->timing.min_refresh_in_uhz;
127	if (stream->ctx->dc->caps.max_v_total != 0) {
128		if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0) {
129			pix_clk_100hz = pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz;
130		} else {
131			pix_clk_100hz = stream->timing.pix_clk_100hz;
132		}
133		min_hardware_refresh_in_uhz = div64_u64((pix_clk_100hz * 100000000ULL),
134				(timing->h_total * (long long)calc_max_hardware_v_total(stream)));
135	}
136
137	timing->drr_config.min_refresh_uhz = max(stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz);
138
139	if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
140			stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
141		timing->drr_config.max_instant_vtotal_delta = dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase(stream, false);
142	else
143		timing->drr_config.max_instant_vtotal_delta = 0;
144
145	if (stream->timing.flags.DSC) {
146		timing->dsc.enable = dml2_dsc_enable;
147		timing->dsc.overrides.num_slices = stream->timing.dsc_cfg.num_slices_h;
148		timing->dsc.dsc_compressed_bpp_x16 = stream->timing.dsc_cfg.bits_per_pixel;
149	} else
150		timing->dsc.enable = dml2_dsc_disable;
151
152	switch (stream->timing.display_color_depth) {
153	case COLOR_DEPTH_666:
154		timing->bpc = 6;
155		break;
156	case COLOR_DEPTH_888:
157		timing->bpc = 8;
158		break;
159	case COLOR_DEPTH_101010:
160		timing->bpc = 10;
161		break;
162	case COLOR_DEPTH_121212:
163		timing->bpc = 12;
164		break;
165	case COLOR_DEPTH_141414:
166		timing->bpc = 14;
167		break;
168	case COLOR_DEPTH_161616:
169		timing->bpc = 16;
170		break;
171	case COLOR_DEPTH_999:
172		timing->bpc = 9;
173		break;
174	case COLOR_DEPTH_111111:
175		timing->bpc = 11;
176		break;
177	default:
178		timing->bpc = 8;
179		break;
180	}
181
182	timing->vblank_nom = timing->v_total - timing->v_active;
183}
184
185static void populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg *output,
186		struct dc_stream_state *stream, const struct pipe_ctx *pipe)
187{
188	output->output_dp_lane_count = 4;
189
190	switch (stream->signal) {
191	case SIGNAL_TYPE_DISPLAY_PORT_MST:
192	case SIGNAL_TYPE_DISPLAY_PORT:
193		output->output_encoder = dml2_dp;
194		if (check_dp2p0_output_encoder(pipe))
195			output->output_encoder = dml2_dp2p0;
196		break;
197	case SIGNAL_TYPE_EDP:
198		output->output_encoder = dml2_edp;
199		break;
200	case SIGNAL_TYPE_HDMI_TYPE_A:
201	case SIGNAL_TYPE_DVI_SINGLE_LINK:
202	case SIGNAL_TYPE_DVI_DUAL_LINK:
203		output->output_encoder = dml2_hdmi;
204		break;
205	default:
206			output->output_encoder = dml2_dp;
207	}
208
209	switch (stream->timing.pixel_encoding) {
210	case PIXEL_ENCODING_RGB:
211	case PIXEL_ENCODING_YCBCR444:
212		output->output_format = dml2_444;
213		break;
214	case PIXEL_ENCODING_YCBCR420:
215		output->output_format = dml2_420;
216		break;
217	case PIXEL_ENCODING_YCBCR422:
218		if (stream->timing.flags.DSC && !stream->timing.dsc_cfg.ycbcr422_simple)
219			output->output_format = dml2_n422;
220		else
221			output->output_format = dml2_s422;
222		break;
223	default:
224		output->output_format = dml2_444;
225		break;
226	}
227
228	switch (stream->signal) {
229	case SIGNAL_TYPE_NONE:
230	case SIGNAL_TYPE_DVI_SINGLE_LINK:
231	case SIGNAL_TYPE_DVI_DUAL_LINK:
232	case SIGNAL_TYPE_HDMI_TYPE_A:
233	case SIGNAL_TYPE_LVDS:
234	case SIGNAL_TYPE_RGB:
235	case SIGNAL_TYPE_DISPLAY_PORT:
236	case SIGNAL_TYPE_DISPLAY_PORT_MST:
237	case SIGNAL_TYPE_EDP:
238	case SIGNAL_TYPE_VIRTUAL:
239	default:
240		output->output_dp_link_rate = dml2_dp_rate_na;
241		break;
242	}
243
244	output->audio_sample_layout = stream->audio_info.modes->sample_size;
245	output->audio_sample_rate = stream->audio_info.modes->max_bit_rate;
246	output->output_disabled = true;
247
248	//TODO : New to DML2.1. How do we populate this ?
249	// output->validate_output
250}
251
252static void populate_dml21_stream_overrides_from_stream_state(
253		struct dml2_stream_parameters *stream_desc,
254		struct dc_stream_state *stream,
255		struct dc_stream_status *stream_status)
256{
257	switch (stream->debug.force_odm_combine_segments) {
258	case 0:
259		stream_desc->overrides.odm_mode = dml2_odm_mode_auto;
260		break;
261	case 1:
262		stream_desc->overrides.odm_mode = dml2_odm_mode_bypass;
263		break;
264	case 2:
265		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_2to1;
266		break;
267	case 3:
268		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_3to1;
269		break;
270	case 4:
271		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_4to1;
272		break;
273	default:
274		stream_desc->overrides.odm_mode =  dml2_odm_mode_auto;
275		break;
276	}
277	if (!stream->ctx->dc->debug.enable_single_display_2to1_odm_policy ||
278			stream->debug.force_odm_combine_segments > 0)
279		stream_desc->overrides.disable_dynamic_odm = true;
280	stream_desc->overrides.disable_subvp = stream->ctx->dc->debug.force_disable_subvp ||
281			stream->hw_cursor_req ||
282			stream_status->mall_stream_config.cursor_size_limit_subvp;
283}
284
285static enum dml2_swizzle_mode gfx_addr3_to_dml2_swizzle_mode(enum swizzle_mode_addr3_values addr3_mode)
286{
287	enum dml2_swizzle_mode dml2_mode = dml2_sw_linear;
288
289	switch (addr3_mode) {
290	case DC_ADDR3_SW_LINEAR:
291		dml2_mode = dml2_sw_linear;
292		break;
293	case DC_ADDR3_SW_256B_2D:
294		dml2_mode = dml2_sw_256b_2d;
295		break;
296	case DC_ADDR3_SW_4KB_2D:
297		dml2_mode = dml2_sw_4kb_2d;
298		break;
299	case DC_ADDR3_SW_64KB_2D:
300		dml2_mode = dml2_sw_64kb_2d;
301		break;
302	case DC_ADDR3_SW_256KB_2D:
303		dml2_mode = dml2_sw_256kb_2d;
304		break;
305	default:
306		/* invalid swizzle mode for DML2.1 */
307		ASSERT(false);
308		dml2_mode = dml2_sw_linear;
309	}
310
311	return dml2_mode;
312}
313
314static enum dml2_swizzle_mode gfx9_to_dml2_swizzle_mode(enum swizzle_mode_values gfx9_mode)
315{
316	enum dml2_swizzle_mode dml2_mode = dml2_sw_64kb_2d;
317
318	switch (gfx9_mode) {
319	case DC_SW_LINEAR:
320		dml2_mode = dml2_sw_linear;
321		break;
322	case DC_SW_256_D:
323	case DC_SW_256_R:
324		dml2_mode = dml2_sw_256b_2d;
325		break;
326	case DC_SW_4KB_D:
327	case DC_SW_4KB_R:
328	case DC_SW_4KB_R_X:
329		dml2_mode = dml2_sw_4kb_2d;
330		break;
331	case DC_SW_64KB_D:
332	case DC_SW_64KB_D_X:
333	case DC_SW_64KB_R:
334	case DC_SW_64KB_R_X:
335		dml2_mode = dml2_sw_64kb_2d;
336		break;
337	case DC_SW_256B_S:
338	case DC_SW_4KB_S:
339	case DC_SW_64KB_S:
340	case DC_SW_VAR_S:
341	case DC_SW_VAR_D:
342	case DC_SW_VAR_R:
343	case DC_SW_64KB_S_T:
344	case DC_SW_64KB_D_T:
345	case DC_SW_4KB_S_X:
346	case DC_SW_4KB_D_X:
347	case DC_SW_64KB_S_X:
348	case DC_SW_VAR_S_X:
349	case DC_SW_VAR_D_X:
350	case DC_SW_VAR_R_X:
351	default:
352		/*
353		 * invalid swizzle mode for DML2.1. This could happen because
354		 * DML21 is not intended to be used by N-1 in production. To
355		 * properly filter out unsupported swizzle modes, we will need
356		 * to fix capability reporting when DML2.1 is used for N-1 in
357		 * dc. So DML will only receive DML21 supported swizzle modes.
358		 * This implementation is not added and has a low value because
359		 * the supported swizzle modes should already cover most of our
360		 * N-1 test cases.
361		 */
362		return dml2_sw_64kb_2d;
363	}
364
365	return dml2_mode;
366}
367
368static void populate_dml21_dummy_surface_cfg(struct dml2_surface_cfg *surface, const struct dc_stream_state *stream)
369{
370	surface->plane0.width = stream->timing.h_addressable;
371	surface->plane0.height = stream->timing.v_addressable;
372	surface->plane1.width = stream->timing.h_addressable;
373	surface->plane1.height = stream->timing.v_addressable;
374	surface->plane0.pitch = ((surface->plane0.width + 127) / 128) * 128;
375	surface->plane1.pitch = 0;
376	surface->dcc.enable = false;
377	surface->dcc.informative.dcc_rate_plane0 = 1.0;
378	surface->dcc.informative.dcc_rate_plane1 = 1.0;
379	surface->dcc.informative.fraction_of_zero_size_request_plane0 = 0;
380	surface->dcc.informative.fraction_of_zero_size_request_plane1 = 0;
381	surface->tiling = dml2_sw_64kb_2d;
382}
383
384static void populate_dml21_dummy_plane_cfg(struct dml2_plane_parameters *plane, const struct dc_stream_state *stream)
385{
386	unsigned int width, height;
387
388	if (stream->timing.h_addressable > 3840)
389		width = 3840;
390	else
391		width = stream->timing.h_addressable;	// 4K max
392
393	if (stream->timing.v_addressable > 2160)
394		height = 2160;
395	else
396		height = stream->timing.v_addressable;	// 4K max
397
398	plane->cursor.cursor_bpp = 32;
399
400	plane->cursor.cursor_width = 256;
401	plane->cursor.num_cursors = 1;
402
403	plane->composition.viewport.plane0.width = width;
404	plane->composition.viewport.plane0.height = height;
405	plane->composition.viewport.plane1.width = 0;
406	plane->composition.viewport.plane1.height = 0;
407
408	plane->composition.viewport.stationary = false;
409	plane->composition.viewport.plane0.x_start = 0;
410	plane->composition.viewport.plane0.y_start = 0;
411	plane->composition.viewport.plane1.x_start = 0;
412	plane->composition.viewport.plane1.y_start = 0;
413
414	plane->composition.scaler_info.enabled = false;
415	plane->composition.rotation_angle = dml2_rotation_0;
416	plane->composition.scaler_info.plane0.h_ratio = 1.0;
417	plane->composition.scaler_info.plane0.v_ratio = 1.0;
418	plane->composition.scaler_info.plane1.h_ratio = 0;
419	plane->composition.scaler_info.plane1.v_ratio = 0;
420	plane->composition.scaler_info.plane0.h_taps = 1;
421	plane->composition.scaler_info.plane0.v_taps = 1;
422	plane->composition.scaler_info.plane1.h_taps = 0;
423	plane->composition.scaler_info.plane1.v_taps = 0;
424	plane->composition.scaler_info.rect_out_width = width;
425	plane->pixel_format = dml2_444_32;
426
427	plane->dynamic_meta_data.enable = false;
428	plane->overrides.gpuvm_min_page_size_kbytes = 256;
429}
430
431static void populate_dml21_surface_config_from_plane_state(
432		const struct dc *in_dc,
433		struct dml2_surface_cfg *surface,
434		const struct dc_plane_state *plane_state)
435{
436	surface->plane0.pitch = plane_state->plane_size.surface_pitch;
437	surface->plane1.pitch = plane_state->plane_size.chroma_pitch;
438	surface->plane0.height = plane_state->plane_size.surface_size.height;
439	surface->plane0.width = plane_state->plane_size.surface_size.width;
440	surface->plane1.height = plane_state->plane_size.chroma_size.height;
441	surface->plane1.width = plane_state->plane_size.chroma_size.width;
442	surface->dcc.enable = plane_state->dcc.enable;
443	surface->dcc.informative.dcc_rate_plane0 = 1.0;
444	surface->dcc.informative.dcc_rate_plane1 = 1.0;
445	surface->dcc.informative.fraction_of_zero_size_request_plane0 = plane_state->dcc.independent_64b_blks;
446	surface->dcc.informative.fraction_of_zero_size_request_plane1 = plane_state->dcc.independent_64b_blks_c;
447	surface->dcc.plane0.pitch = plane_state->dcc.meta_pitch;
448	surface->dcc.plane1.pitch = plane_state->dcc.meta_pitch_c;
449
450	// Update swizzle / array mode based on the gfx_format
451	switch (plane_state->tiling_info.gfxversion) {
452	case DcGfxVersion7:
453	case DcGfxVersion8:
454		break;
455	case DcGfxVersion9:
456	case DcGfxVersion10:
457	case DcGfxVersion11:
458		surface->tiling = gfx9_to_dml2_swizzle_mode(plane_state->tiling_info.gfx9.swizzle);
459		break;
460	case DcGfxAddr3:
461		surface->tiling = gfx_addr3_to_dml2_swizzle_mode(plane_state->tiling_info.gfx_addr3.swizzle);
462		break;
463	}
464}
465
466static const struct scaler_data *get_scaler_data_for_plane(
467		struct dml2_context *dml_ctx,
468		const struct dc_plane_state *in,
469		const struct dc_state *context)
470{
471	int i;
472	struct pipe_ctx *temp_pipe = &dml_ctx->v21.scratch.temp_pipe;
473
474	memset(temp_pipe, 0, sizeof(struct pipe_ctx));
475
476	for (i = 0; i < MAX_PIPES; i++)	{
477		const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
478
479		if (pipe->plane_state == in && !pipe->prev_odm_pipe) {
480			temp_pipe->stream = pipe->stream;
481			temp_pipe->plane_state = pipe->plane_state;
482			temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps;
483			temp_pipe->stream_res = pipe->stream_res;
484			temp_pipe->dsc_padding_params.dsc_hactive_padding = pipe->dsc_padding_params.dsc_hactive_padding;
485			temp_pipe->dsc_padding_params.dsc_htotal_padding = pipe->dsc_padding_params.dsc_htotal_padding;
486			temp_pipe->dsc_padding_params.dsc_pix_clk_100hz = pipe->dsc_padding_params.dsc_pix_clk_100hz;
487			dml_ctx->config.callbacks.build_scaling_params(temp_pipe);
488			break;
489		}
490	}
491
492	ASSERT(i < MAX_PIPES);
493	return &temp_pipe->plane_res.scl_data;
494}
495
496static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dml_ctx,
497		struct dml2_plane_parameters *plane, const struct dc_plane_state *plane_state,
498		const struct dc_state *context, unsigned int stream_index)
499{
500	const struct scaler_data *scaler_data = get_scaler_data_for_plane(dml_ctx, plane_state, context);
501	struct dc_stream_state *stream = context->streams[stream_index];
502
503	plane->cursor.cursor_bpp = 32;
504	plane->cursor.cursor_width = 256;
505	plane->cursor.num_cursors = 1;
506
507	switch (plane_state->format) {
508	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
509	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
510		plane->pixel_format = dml2_420_8;
511		break;
512	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
513	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
514		plane->pixel_format = dml2_420_10;
515		break;
516	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
517	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
518	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
519	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
520		plane->pixel_format = dml2_444_64;
521		break;
522	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
523	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
524		plane->pixel_format = dml2_444_16;
525		break;
526	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
527		plane->pixel_format = dml2_444_8;
528		break;
529	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
530		plane->pixel_format = dml2_rgbe_alpha;
531		break;
532	default:
533		plane->pixel_format = dml2_444_32;
534		break;
535	}
536
537	plane->composition.viewport.plane0.height = scaler_data->viewport.height;
538	plane->composition.viewport.plane0.width = scaler_data->viewport.width;
539	plane->composition.viewport.plane1.height = scaler_data->viewport_c.height;
540	plane->composition.viewport.plane1.width = scaler_data->viewport_c.width;
541	plane->composition.viewport.plane0.x_start = scaler_data->viewport.x;
542	plane->composition.viewport.plane0.y_start = scaler_data->viewport.y;
543	plane->composition.viewport.plane1.x_start = scaler_data->viewport_c.x;
544	plane->composition.viewport.plane1.y_start = scaler_data->viewport_c.y;
545	plane->composition.viewport.stationary = false;
546	plane->composition.scaler_info.enabled = scaler_data->ratios.horz.value != dc_fixpt_one.value ||
547		scaler_data->ratios.horz_c.value != dc_fixpt_one.value ||
548		scaler_data->ratios.vert.value != dc_fixpt_one.value ||
549		scaler_data->ratios.vert_c.value != dc_fixpt_one.value;
550
551	if (!scaler_data->taps.h_taps) {
552		/* Above logic determines scaling should be enabled even when there are no taps for
553		 * certain cases. Hence do corrective active and disable scaling.
554		 */
555		plane->composition.scaler_info.enabled = false;
556	} else if ((plane_state->ctx->dc->config.use_spl == true) &&
557		(plane->composition.scaler_info.enabled == false)) {
558		/* To enable sharpener for 1:1, scaler must be enabled.  If use_spl is set, then
559		 *  allow case where ratio is 1 but taps > 1
560		 */
561		if ((scaler_data->taps.h_taps > 1) || (scaler_data->taps.v_taps > 1) ||
562			(scaler_data->taps.h_taps_c > 1) || (scaler_data->taps.v_taps_c > 1))
563			plane->composition.scaler_info.enabled = true;
564	}
565
566	/* always_scale is only used for debug purposes not used in production but has to be
567	 * maintained for certain complainces. */
568	if (plane_state->ctx->dc->debug.always_scale == true) {
569		plane->composition.scaler_info.enabled = true;
570	}
571
572	if (plane->composition.scaler_info.enabled == false) {
573		plane->composition.scaler_info.plane0.h_ratio = 1.0;
574		plane->composition.scaler_info.plane0.v_ratio = 1.0;
575		plane->composition.scaler_info.plane1.h_ratio = 1.0;
576		plane->composition.scaler_info.plane1.v_ratio = 1.0;
577	} else {
578		plane->composition.scaler_info.plane0.h_ratio = (double)scaler_data->ratios.horz.value / (1ULL << 32);
579		plane->composition.scaler_info.plane0.v_ratio = (double)scaler_data->ratios.vert.value / (1ULL << 32);
580		plane->composition.scaler_info.plane1.h_ratio = (double)scaler_data->ratios.horz_c.value / (1ULL << 32);
581		plane->composition.scaler_info.plane1.v_ratio = (double)scaler_data->ratios.vert_c.value / (1ULL << 32);
582	}
583
584	if (!scaler_data->taps.h_taps) {
585		plane->composition.scaler_info.plane0.h_taps = 1;
586		plane->composition.scaler_info.plane1.h_taps = 1;
587	} else {
588		plane->composition.scaler_info.plane0.h_taps = scaler_data->taps.h_taps;
589		plane->composition.scaler_info.plane1.h_taps = scaler_data->taps.h_taps_c;
590	}
591	if (!scaler_data->taps.v_taps) {
592		plane->composition.scaler_info.plane0.v_taps = 1;
593		plane->composition.scaler_info.plane1.v_taps = 1;
594	} else {
595		plane->composition.scaler_info.plane0.v_taps = scaler_data->taps.v_taps;
596		plane->composition.scaler_info.plane1.v_taps = scaler_data->taps.v_taps_c;
597	}
598
599	plane->composition.viewport.stationary = false;
600
601	if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
602		plane->tdlut.setup_for_tdlut = true;
603
604		switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.layout) {
605		case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
606		case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
607			plane->tdlut.tdlut_addressing_mode = dml2_tdlut_sw_linear;
608			break;
609		case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
610			plane->tdlut.tdlut_addressing_mode = dml2_tdlut_simple_linear;
611			break;
612		}
613
614		switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.size) {
615		case DC_CM2_GPU_MEM_SIZE_171717:
616			plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
617			break;
618		case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
619		default:
620			//plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
621			break;
622		}
623	}
624	plane->tdlut.setup_for_tdlut |= dml_ctx->config.force_tdlut_enable;
625
626	plane->dynamic_meta_data.enable = false;
627	plane->dynamic_meta_data.lines_before_active_required = 0;
628	plane->dynamic_meta_data.transmitted_bytes = 0;
629
630	plane->composition.scaler_info.rect_out_width = plane_state->dst_rect.width;
631	plane->composition.rotation_angle = (enum dml2_rotation_angle) plane_state->rotation;
632	plane->stream_index = stream_index;
633
634	plane->overrides.gpuvm_min_page_size_kbytes = 256;
635
636	plane->immediate_flip = plane_state->flip_immediate;
637
638	plane->composition.rect_out_height_spans_vactive =
639		plane_state->dst_rect.height >= stream->src.height &&
640		stream->dst.height >= stream->timing.v_addressable;
641}
642
643//TODO : Could be possibly moved to a common helper layer.
644static bool dml21_wrapper_get_plane_id(const struct dc_state *context, unsigned int stream_id, const struct dc_plane_state *plane, unsigned int *plane_id)
645{
646	int i, j;
647
648	if (!plane_id)
649		return false;
650
651	for (i = 0; i < context->stream_count; i++) {
652		if (context->streams[i]->stream_id == stream_id) {
653			for (j = 0; j < context->stream_status[i].plane_count; j++) {
654				if (context->stream_status[i].plane_states[j] == plane) {
655					*plane_id = (i << 16) | j;
656					return true;
657				}
658			}
659		}
660	}
661
662	return false;
663}
664
665static unsigned int map_stream_to_dml21_display_cfg(const struct dml2_context *dml_ctx, const struct dc_stream_state *stream)
666{
667	int i = 0;
668	int location = -1;
669
670	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
671		if (dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id_valid[i] && dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[i] == stream->stream_id) {
672			location = i;
673			break;
674		}
675	}
676
677	return location;
678}
679
680unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id,
681		const struct dc_plane_state *plane, const struct dc_state *context)
682{
683	unsigned int plane_id;
684	int i = 0;
685	int location = -1;
686
687	if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) {
688		ASSERT(false);
689		return -1;
690	}
691
692	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
693		if (dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[i] && dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[i] == plane_id) {
694			location = i;
695			break;
696		}
697	}
698
699	return location;
700}
701
702static enum dml2_uclk_pstate_change_strategy dml21_force_pstate_method_to_uclk_state_change_strategy(enum dml2_force_pstate_methods force_pstate_method)
703{
704	enum dml2_uclk_pstate_change_strategy val = dml2_uclk_pstate_change_strategy_auto;
705
706	switch (force_pstate_method) {
707	case dml2_force_pstate_method_vactive:
708		val = dml2_uclk_pstate_change_strategy_force_vactive;
709		break;
710	case dml2_force_pstate_method_vblank:
711		val = dml2_uclk_pstate_change_strategy_force_vblank;
712		break;
713	case dml2_force_pstate_method_drr:
714		val = dml2_uclk_pstate_change_strategy_force_drr;
715		break;
716	case dml2_force_pstate_method_subvp:
717		val = dml2_uclk_pstate_change_strategy_force_mall_svp;
718		break;
719	case dml2_force_pstate_method_auto:
720	default:
721		val = dml2_uclk_pstate_change_strategy_auto;
722	}
723
724	return val;
725}
726
727bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
728{
729	int stream_index, plane_index;
730	int disp_cfg_stream_location, disp_cfg_plane_location;
731	struct dml2_display_cfg *dml_dispcfg = &dml_ctx->v21.display_config;
732	unsigned int plane_count = 0;
733
734	memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
735
736	dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable;
737	dml_dispcfg->gpuvm_max_page_table_levels = 4;
738	dml_dispcfg->hostvm_enable = false;
739	dml_dispcfg->minimize_det_reallocation = true;
740	dml_dispcfg->overrides.enable_subvp_implicit_pmo = true;
741
742	if (in_dc->debug.disable_unbounded_requesting) {
743		dml_dispcfg->overrides.hw.force_unbounded_requesting.enable = true;
744		dml_dispcfg->overrides.hw.force_unbounded_requesting.value = false;
745	}
746
747	for (stream_index = 0; stream_index < context->stream_count; stream_index++) {
748		disp_cfg_stream_location = map_stream_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]);
749
750		if (disp_cfg_stream_location < 0)
751			disp_cfg_stream_location = dml_dispcfg->num_streams++;
752
753		ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__);
754		populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index], dml_ctx);
755		populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]);
756		populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index], &context->stream_status[stream_index]);
757
758		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.fclk_pstate = dml2_twait_budgeting_setting_if_needed;
759		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.uclk_pstate = dml2_twait_budgeting_setting_if_needed;
760		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.stutter_enter_exit = dml2_twait_budgeting_setting_if_needed;
761
762		dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[disp_cfg_stream_location] = context->streams[stream_index]->stream_id;
763		dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id_valid[disp_cfg_stream_location] = true;
764
765		if (context->stream_status[stream_index].plane_count == 0) {
766			disp_cfg_plane_location = dml_dispcfg->num_planes++;
767			populate_dml21_dummy_surface_cfg(&dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->streams[stream_index]);
768			populate_dml21_dummy_plane_cfg(&dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->streams[stream_index]);
769			dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
770		} else {
771			for (plane_index = 0; plane_index < context->stream_status[stream_index].plane_count; plane_index++) {
772				disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], context);
773
774				if (disp_cfg_plane_location < 0)
775					disp_cfg_plane_location = dml_dispcfg->num_planes++;
776
777				ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__);
778
779				populate_dml21_surface_config_from_plane_state(in_dc, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->stream_status[stream_index].plane_states[plane_index]);
780				populate_dml21_plane_config_from_plane_state(dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->stream_status[stream_index].plane_states[plane_index], context, stream_index);
781				dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
782
783				if (dml21_wrapper_get_plane_id(context, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], &dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[disp_cfg_plane_location]))
784					dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true;
785
786				/* apply forced pstate policy */
787				if (dml_ctx->config.pmo.force_pstate_method_enable) {
788					dml_dispcfg->plane_descriptors[disp_cfg_plane_location].overrides.uclk_pstate_change_strategy =
789							dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_values[stream_index]);
790				}
791
792				plane_count++;
793			}
794		}
795	}
796
797	if (plane_count == 0) {
798		dml_dispcfg->overrides.all_streams_blanked = true;
799	}
800
801	return true;
802}
803
804void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state *context)
805{
806	/* TODO these should be the max of active, svp prefetch and idle should be tracked seperately */
807	context->bw_ctx.bw.dcn.clk.dispclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dispclk_khz;
808	context->bw_ctx.bw.dcn.clk.dcfclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.dcfclk_khz;
809	context->bw_ctx.bw.dcn.clk.dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.uclk_khz;
810	context->bw_ctx.bw.dcn.clk.fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.fclk_khz;
811	context->bw_ctx.bw.dcn.clk.idle_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.idle.uclk_khz;
812	context->bw_ctx.bw.dcn.clk.idle_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.idle.fclk_khz;
813	context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.deepsleep_dcfclk_khz;
814	context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = in_ctx->v21.mode_programming.programming->fclk_pstate_supported;
815	context->bw_ctx.bw.dcn.clk.p_state_change_support = in_ctx->v21.mode_programming.programming->uclk_pstate_supported;
816	context->bw_ctx.bw.dcn.clk.dtbclk_en = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dtbrefclk_khz > 0;
817	context->bw_ctx.bw.dcn.clk.ref_dtbclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dtbrefclk_khz;
818	context->bw_ctx.bw.dcn.clk.socclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.socclk_khz;
819	context->bw_ctx.bw.dcn.clk.subvp_prefetch_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.uclk_khz;
820	context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz;
821	context->bw_ctx.bw.dcn.clk.stutter_efficiency.base_efficiency = in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency;
822	context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency;
823}
824
825static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index)
826{
827	struct dml2_dchub_watermark_regs *wm_regs = NULL;
828
829	switch (wm_index) {
830	case DML2_DCHUB_WATERMARK_SET_A:
831		wm_regs = &watermarks->dcn4x.a;
832		break;
833	case DML2_DCHUB_WATERMARK_SET_B:
834		wm_regs = &watermarks->dcn4x.b;
835		break;
836	case DML2_DCHUB_WATERMARK_SET_C:
837		wm_regs = &watermarks->dcn4x.c;
838		break;
839	case DML2_DCHUB_WATERMARK_SET_D:
840		wm_regs = &watermarks->dcn4x.d;
841		break;
842	case DML2_DCHUB_WATERMARK_SET_NUM:
843	default:
844		/* invalid wm set index */
845		wm_regs = NULL;
846	}
847
848	return wm_regs;
849}
850
851void dml21_extract_watermark_sets(const struct dc *in_dc, union dcn_watermark_set *watermarks, struct dml2_context *in_ctx)
852{
853	const struct dml2_display_cfg_programming *programming = in_ctx->v21.mode_programming.programming;
854
855	unsigned int wm_index;
856
857	/* copy watermark sets from DML */
858	for (wm_index = 0; wm_index < programming->global_regs.num_watermark_sets; wm_index++) {
859		struct dml2_dchub_watermark_regs *wm_regs = wm_set_index_to_dc_wm_set(watermarks, wm_index);
860
861		if (wm_regs)
862			memcpy(wm_regs,
863				&programming->global_regs.wm_regs[wm_index],
864				sizeof(struct dml2_dchub_watermark_regs));
865	}
866}
867
868void dml21_map_hw_resources(struct dml2_context *dml_ctx)
869{
870	unsigned int i = 0;
871
872	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
873		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[i] = dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[i];
874		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[i] = true;
875		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[i] = dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[i];
876		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[i] = true;
877	}
878
879}
880
881void dml21_get_pipe_mcache_config(
882	struct dc_state *context,
883	struct pipe_ctx *pipe_ctx,
884	struct dml2_per_plane_programming *pln_prog,
885	struct dml2_pipe_configuration_descriptor *mcache_pipe_config)
886{
887	mcache_pipe_config->plane0.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x;
888	mcache_pipe_config->plane0.viewport_width = pipe_ctx->plane_res.scl_data.viewport.width;
889
890	mcache_pipe_config->plane1.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport_c.x;
891	mcache_pipe_config->plane1.viewport_width = pipe_ctx->plane_res.scl_data.viewport_c.width;
892
893	mcache_pipe_config->plane1_enabled =
894			dml21_is_plane1_enabled(pln_prog->plane_descriptor->pixel_format);
895}
896
897void dml21_set_dc_p_state_type(
898		struct pipe_ctx *pipe_ctx,
899		struct dml2_per_stream_programming *stream_programming,
900		bool sub_vp_enabled)
901{
902	switch (stream_programming->uclk_pstate_method) {
903	case dml2_pstate_method_vactive:
904	case dml2_pstate_method_fw_vactive_drr:
905		pipe_ctx->p_state_type = P_STATE_V_ACTIVE;
906		break;
907	case dml2_pstate_method_vblank:
908	case dml2_pstate_method_fw_vblank_drr:
909		if (sub_vp_enabled)
910			pipe_ctx->p_state_type = P_STATE_V_BLANK_SUB_VP;
911		else
912			pipe_ctx->p_state_type = P_STATE_V_BLANK;
913		break;
914	case dml2_pstate_method_fw_svp:
915	case dml2_pstate_method_fw_svp_drr:
916		pipe_ctx->p_state_type = P_STATE_SUB_VP;
917		break;
918	case dml2_pstate_method_fw_drr:
919		if (sub_vp_enabled)
920			pipe_ctx->p_state_type = P_STATE_DRR_SUB_VP;
921		else
922			pipe_ctx->p_state_type = P_STATE_FPO;
923		break;
924	default:
925		pipe_ctx->p_state_type = P_STATE_UNKNOWN;
926		break;
927	}
928}
929
~/ Read-only file preview.