1 /*
2  * Copyright 2012-15 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 #include <linux/slab.h>
27 
28 #include "dm_services.h"
29 
30 #include "resource.h"
31 #include "include/irq_service_interface.h"
32 #include "link_encoder.h"
33 #include "stream_encoder.h"
34 #include "opp.h"
35 #include "timing_generator.h"
36 #include "transform.h"
37 #include "dccg.h"
38 #include "dchubbub.h"
39 #include "dpp.h"
40 #include "core_types.h"
41 #include "set_mode_types.h"
42 #include "virtual/virtual_stream_encoder.h"
43 #include "dpcd_defs.h"
44 
45 #if defined(CONFIG_DRM_AMD_DC_SI)
46 #include "dce60/dce60_resource.h"
47 #endif
48 #include "dce80/dce80_resource.h"
49 #include "dce100/dce100_resource.h"
50 #include "dce110/dce110_resource.h"
51 #include "dce112/dce112_resource.h"
52 #include "dce120/dce120_resource.h"
53 #if defined(CONFIG_DRM_AMD_DC_DCN)
54 #include "dcn10/dcn10_resource.h"
55 #include "dcn20/dcn20_resource.h"
56 #include "dcn21/dcn21_resource.h"
57 #include "dcn30/dcn30_resource.h"
58 #include "dcn301/dcn301_resource.h"
59 #include "dcn302/dcn302_resource.h"
60 #include "dcn303/dcn303_resource.h"
61 #endif
62 
63 #define DC_LOGGER_INIT(logger)
64 
65 enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
66 {
67 	enum dce_version dc_version = DCE_VERSION_UNKNOWN;
68 	switch (asic_id.chip_family) {
69 
70 #if defined(CONFIG_DRM_AMD_DC_SI)
71 	case FAMILY_SI:
72 		if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) ||
73 		    ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) ||
74 		    ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev))
75 			dc_version = DCE_VERSION_6_0;
76 		else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev))
77 			dc_version = DCE_VERSION_6_4;
78 		else
79 			dc_version = DCE_VERSION_6_1;
80 		break;
81 #endif
82 	case FAMILY_CI:
83 		dc_version = DCE_VERSION_8_0;
84 		break;
85 	case FAMILY_KV:
86 		if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) ||
87 		    ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) ||
88 		    ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev))
89 			dc_version = DCE_VERSION_8_3;
90 		else
91 			dc_version = DCE_VERSION_8_1;
92 		break;
93 	case FAMILY_CZ:
94 		dc_version = DCE_VERSION_11_0;
95 		break;
96 
97 	case FAMILY_VI:
98 		if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
99 				ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
100 			dc_version = DCE_VERSION_10_0;
101 			break;
102 		}
103 		if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
104 				ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
105 				ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
106 			dc_version = DCE_VERSION_11_2;
107 		}
108 		if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev))
109 			dc_version = DCE_VERSION_11_22;
110 		break;
111 	case FAMILY_AI:
112 		if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev))
113 			dc_version = DCE_VERSION_12_1;
114 		else
115 			dc_version = DCE_VERSION_12_0;
116 		break;
117 #if defined(CONFIG_DRM_AMD_DC_DCN)
118 	case FAMILY_RV:
119 		dc_version = DCN_VERSION_1_0;
120 		if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev))
121 			dc_version = DCN_VERSION_1_01;
122 		if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev))
123 			dc_version = DCN_VERSION_2_1;
124 		if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev))
125 			dc_version = DCN_VERSION_2_1;
126 		break;
127 
128 	case FAMILY_NV:
129 		dc_version = DCN_VERSION_2_0;
130 		if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev))
131 			dc_version = DCN_VERSION_3_0;
132 		if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev))
133 			dc_version = DCN_VERSION_3_02;
134 		if (ASICREV_IS_BEIGE_GOBY_P(asic_id.hw_internal_rev))
135 			dc_version = DCN_VERSION_3_03;
136 		break;
137 
138 	case FAMILY_VGH:
139 		dc_version = DCN_VERSION_3_01;
140 		break;
141 #endif
142 	default:
143 		dc_version = DCE_VERSION_UNKNOWN;
144 		break;
145 	}
146 	return dc_version;
147 }
148 
149 struct resource_pool *dc_create_resource_pool(struct dc  *dc,
150 					      const struct dc_init_data *init_data,
151 					      enum dce_version dc_version)
152 {
153 	struct resource_pool *res_pool = NULL;
154 
155 	switch (dc_version) {
156 #if defined(CONFIG_DRM_AMD_DC_SI)
157 	case DCE_VERSION_6_0:
158 		res_pool = dce60_create_resource_pool(
159 			init_data->num_virtual_links, dc);
160 		break;
161 	case DCE_VERSION_6_1:
162 		res_pool = dce61_create_resource_pool(
163 			init_data->num_virtual_links, dc);
164 		break;
165 	case DCE_VERSION_6_4:
166 		res_pool = dce64_create_resource_pool(
167 			init_data->num_virtual_links, dc);
168 		break;
169 #endif
170 	case DCE_VERSION_8_0:
171 		res_pool = dce80_create_resource_pool(
172 				init_data->num_virtual_links, dc);
173 		break;
174 	case DCE_VERSION_8_1:
175 		res_pool = dce81_create_resource_pool(
176 				init_data->num_virtual_links, dc);
177 		break;
178 	case DCE_VERSION_8_3:
179 		res_pool = dce83_create_resource_pool(
180 				init_data->num_virtual_links, dc);
181 		break;
182 	case DCE_VERSION_10_0:
183 		res_pool = dce100_create_resource_pool(
184 				init_data->num_virtual_links, dc);
185 		break;
186 	case DCE_VERSION_11_0:
187 		res_pool = dce110_create_resource_pool(
188 				init_data->num_virtual_links, dc,
189 				init_data->asic_id);
190 		break;
191 	case DCE_VERSION_11_2:
192 	case DCE_VERSION_11_22:
193 		res_pool = dce112_create_resource_pool(
194 				init_data->num_virtual_links, dc);
195 		break;
196 	case DCE_VERSION_12_0:
197 	case DCE_VERSION_12_1:
198 		res_pool = dce120_create_resource_pool(
199 				init_data->num_virtual_links, dc);
200 		break;
201 
202 #if defined(CONFIG_DRM_AMD_DC_DCN)
203 	case DCN_VERSION_1_0:
204 	case DCN_VERSION_1_01:
205 		res_pool = dcn10_create_resource_pool(init_data, dc);
206 		break;
207 	case DCN_VERSION_2_0:
208 		res_pool = dcn20_create_resource_pool(init_data, dc);
209 		break;
210 	case DCN_VERSION_2_1:
211 		res_pool = dcn21_create_resource_pool(init_data, dc);
212 		break;
213 	case DCN_VERSION_3_0:
214 		res_pool = dcn30_create_resource_pool(init_data, dc);
215 		break;
216 	case DCN_VERSION_3_01:
217 		res_pool = dcn301_create_resource_pool(init_data, dc);
218 		break;
219 	case DCN_VERSION_3_02:
220 		res_pool = dcn302_create_resource_pool(init_data, dc);
221 		break;
222 	case DCN_VERSION_3_03:
223 		res_pool = dcn303_create_resource_pool(init_data, dc);
224 		break;
225 #endif
226 	default:
227 		break;
228 	}
229 
230 	if (res_pool != NULL) {
231 		if (dc->ctx->dc_bios->fw_info_valid) {
232 			res_pool->ref_clocks.xtalin_clock_inKhz =
233 				dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
234 			/* initialize with firmware data first, no all
235 			 * ASIC have DCCG SW component. FPGA or
236 			 * simulation need initialization of
237 			 * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz
238 			 * with xtalin_clock_inKhz
239 			 */
240 			res_pool->ref_clocks.dccg_ref_clock_inKhz =
241 				res_pool->ref_clocks.xtalin_clock_inKhz;
242 			res_pool->ref_clocks.dchub_ref_clock_inKhz =
243 				res_pool->ref_clocks.xtalin_clock_inKhz;
244 		} else
245 			ASSERT_CRITICAL(false);
246 	}
247 
248 	return res_pool;
249 }
250 
251 void dc_destroy_resource_pool(struct dc  *dc)
252 {
253 	if (dc) {
254 		if (dc->res_pool)
255 			dc->res_pool->funcs->destroy(&dc->res_pool);
256 
257 		kfree(dc->hwseq);
258 	}
259 }
260 
261 static void update_num_audio(
262 	const struct resource_straps *straps,
263 	unsigned int *num_audio,
264 	struct audio_support *aud_support)
265 {
266 	aud_support->dp_audio = true;
267 	aud_support->hdmi_audio_native = false;
268 	aud_support->hdmi_audio_on_dongle = false;
269 
270 	if (straps->hdmi_disable == 0) {
271 		if (straps->dc_pinstraps_audio & 0x2) {
272 			aud_support->hdmi_audio_on_dongle = true;
273 			aud_support->hdmi_audio_native = true;
274 		}
275 	}
276 
277 	switch (straps->audio_stream_number) {
278 	case 0: /* multi streams supported */
279 		break;
280 	case 1: /* multi streams not supported */
281 		*num_audio = 1;
282 		break;
283 	default:
284 		DC_ERR("DC: unexpected audio fuse!\n");
285 	}
286 }
287 
288 bool resource_construct(
289 	unsigned int num_virtual_links,
290 	struct dc  *dc,
291 	struct resource_pool *pool,
292 	const struct resource_create_funcs *create_funcs)
293 {
294 	struct dc_context *ctx = dc->ctx;
295 	const struct resource_caps *caps = pool->res_cap;
296 	int i;
297 	unsigned int num_audio = caps->num_audio;
298 	struct resource_straps straps = {0};
299 
300 	if (create_funcs->read_dce_straps)
301 		create_funcs->read_dce_straps(dc->ctx, &straps);
302 
303 	pool->audio_count = 0;
304 	if (create_funcs->create_audio) {
305 		/* find the total number of streams available via the
306 		 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
307 		 * registers (one for each pin) starting from pin 1
308 		 * up to the max number of audio pins.
309 		 * We stop on the first pin where
310 		 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
311 		 */
312 		update_num_audio(&straps, &num_audio, &pool->audio_support);
313 		for (i = 0; i < caps->num_audio; i++) {
314 			struct audio *aud = create_funcs->create_audio(ctx, i);
315 
316 			if (aud == NULL) {
317 				DC_ERR("DC: failed to create audio!\n");
318 				return false;
319 			}
320 			if (!aud->funcs->endpoint_valid(aud)) {
321 				aud->funcs->destroy(&aud);
322 				break;
323 			}
324 			pool->audios[i] = aud;
325 			pool->audio_count++;
326 		}
327 	}
328 
329 	pool->stream_enc_count = 0;
330 	if (create_funcs->create_stream_encoder) {
331 		for (i = 0; i < caps->num_stream_encoder; i++) {
332 			pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
333 			if (pool->stream_enc[i] == NULL)
334 				DC_ERR("DC: failed to create stream_encoder!\n");
335 			pool->stream_enc_count++;
336 		}
337 	}
338 
339 #if defined(CONFIG_DRM_AMD_DC_DCN)
340 	for (i = 0; i < caps->num_mpc_3dlut; i++) {
341 		pool->mpc_lut[i] = dc_create_3dlut_func();
342 		if (pool->mpc_lut[i] == NULL)
343 			DC_ERR("DC: failed to create MPC 3dlut!\n");
344 		pool->mpc_shaper[i] = dc_create_transfer_func();
345 		if (pool->mpc_shaper[i] == NULL)
346 			DC_ERR("DC: failed to create MPC shaper!\n");
347 	}
348 #endif
349 	dc->caps.dynamic_audio = false;
350 	if (pool->audio_count < pool->stream_enc_count) {
351 		dc->caps.dynamic_audio = true;
352 	}
353 	for (i = 0; i < num_virtual_links; i++) {
354 		pool->stream_enc[pool->stream_enc_count] =
355 			virtual_stream_encoder_create(
356 					ctx, ctx->dc_bios);
357 		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
358 			DC_ERR("DC: failed to create stream_encoder!\n");
359 			return false;
360 		}
361 		pool->stream_enc_count++;
362 	}
363 
364 	dc->hwseq = create_funcs->create_hwseq(ctx);
365 
366 	return true;
367 }
368 static int find_matching_clock_source(
369 		const struct resource_pool *pool,
370 		struct clock_source *clock_source)
371 {
372 
373 	int i;
374 
375 	for (i = 0; i < pool->clk_src_count; i++) {
376 		if (pool->clock_sources[i] == clock_source)
377 			return i;
378 	}
379 	return -1;
380 }
381 
382 void resource_unreference_clock_source(
383 		struct resource_context *res_ctx,
384 		const struct resource_pool *pool,
385 		struct clock_source *clock_source)
386 {
387 	int i = find_matching_clock_source(pool, clock_source);
388 
389 	if (i > -1)
390 		res_ctx->clock_source_ref_count[i]--;
391 
392 	if (pool->dp_clock_source == clock_source)
393 		res_ctx->dp_clock_source_ref_count--;
394 }
395 
396 void resource_reference_clock_source(
397 		struct resource_context *res_ctx,
398 		const struct resource_pool *pool,
399 		struct clock_source *clock_source)
400 {
401 	int i = find_matching_clock_source(pool, clock_source);
402 
403 	if (i > -1)
404 		res_ctx->clock_source_ref_count[i]++;
405 
406 	if (pool->dp_clock_source == clock_source)
407 		res_ctx->dp_clock_source_ref_count++;
408 }
409 
410 int resource_get_clock_source_reference(
411 		struct resource_context *res_ctx,
412 		const struct resource_pool *pool,
413 		struct clock_source *clock_source)
414 {
415 	int i = find_matching_clock_source(pool, clock_source);
416 
417 	if (i > -1)
418 		return res_ctx->clock_source_ref_count[i];
419 
420 	if (pool->dp_clock_source == clock_source)
421 		return res_ctx->dp_clock_source_ref_count;
422 
423 	return -1;
424 }
425 
426 bool resource_are_vblanks_synchronizable(
427 	struct dc_stream_state *stream1,
428 	struct dc_stream_state *stream2)
429 {
430 	uint32_t base60_refresh_rates[] = {10, 20, 5};
431 	uint8_t i;
432 	uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]);
433 	uint64_t frame_time_diff;
434 
435 	if (stream1->ctx->dc->config.vblank_alignment_dto_params &&
436 		stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&
437 		dc_is_dp_signal(stream1->signal) &&
438 		dc_is_dp_signal(stream2->signal) &&
439 		false == stream1->has_non_synchronizable_pclk &&
440 		false == stream2->has_non_synchronizable_pclk &&
441 		stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&
442 		stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {
443 		/* disable refresh rates higher than 60Hz for now */
444 		if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/
445 				stream1->timing.v_total > 60)
446 			return false;
447 		if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/
448 				stream2->timing.v_total > 60)
449 			return false;
450 		frame_time_diff = (uint64_t)10000 *
451 			stream1->timing.h_total *
452 			stream1->timing.v_total *
453 			stream2->timing.pix_clk_100hz;
454 		frame_time_diff = div_u64(frame_time_diff, stream1->timing.pix_clk_100hz);
455 		frame_time_diff = div_u64(frame_time_diff, stream2->timing.h_total);
456 		frame_time_diff = div_u64(frame_time_diff, stream2->timing.v_total);
457 		for (i = 0; i < rr_count; i++) {
458 			int64_t diff = (int64_t)div_u64(frame_time_diff * base60_refresh_rates[i], 10) - 10000;
459 
460 			if (diff < 0)
461 				diff = -diff;
462 			if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)
463 				return true;
464 		}
465 	}
466 	return false;
467 }
468 
469 bool resource_are_streams_timing_synchronizable(
470 	struct dc_stream_state *stream1,
471 	struct dc_stream_state *stream2)
472 {
473 	if (stream1->timing.h_total != stream2->timing.h_total)
474 		return false;
475 
476 	if (stream1->timing.v_total != stream2->timing.v_total)
477 		return false;
478 
479 	if (stream1->timing.h_addressable
480 				!= stream2->timing.h_addressable)
481 		return false;
482 
483 	if (stream1->timing.v_addressable
484 				!= stream2->timing.v_addressable)
485 		return false;
486 
487 	if (stream1->timing.v_front_porch
488 				!= stream2->timing.v_front_porch)
489 		return false;
490 
491 	if (stream1->timing.pix_clk_100hz
492 				!= stream2->timing.pix_clk_100hz)
493 		return false;
494 
495 	if (stream1->clamping.c_depth != stream2->clamping.c_depth)
496 		return false;
497 
498 	if (stream1->phy_pix_clk != stream2->phy_pix_clk
499 			&& (!dc_is_dp_signal(stream1->signal)
500 			|| !dc_is_dp_signal(stream2->signal)))
501 		return false;
502 
503 	if (stream1->view_format != stream2->view_format)
504 		return false;
505 
506 	if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param)
507 		return false;
508 
509 	return true;
510 }
511 static bool is_dp_and_hdmi_sharable(
512 		struct dc_stream_state *stream1,
513 		struct dc_stream_state *stream2)
514 {
515 	if (stream1->ctx->dc->caps.disable_dp_clk_share)
516 		return false;
517 
518 	if (stream1->clamping.c_depth != COLOR_DEPTH_888 ||
519 		stream2->clamping.c_depth != COLOR_DEPTH_888)
520 		return false;
521 
522 	return true;
523 
524 }
525 
526 static bool is_sharable_clk_src(
527 	const struct pipe_ctx *pipe_with_clk_src,
528 	const struct pipe_ctx *pipe)
529 {
530 	if (pipe_with_clk_src->clock_source == NULL)
531 		return false;
532 
533 	if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
534 		return false;
535 
536 	if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) ||
537 		(dc_is_dp_signal(pipe->stream->signal) &&
538 		!is_dp_and_hdmi_sharable(pipe_with_clk_src->stream,
539 				     pipe->stream)))
540 		return false;
541 
542 	if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
543 			&& dc_is_dual_link_signal(pipe->stream->signal))
544 		return false;
545 
546 	if (dc_is_hdmi_signal(pipe->stream->signal)
547 			&& dc_is_dual_link_signal(pipe_with_clk_src->stream->signal))
548 		return false;
549 
550 	if (!resource_are_streams_timing_synchronizable(
551 			pipe_with_clk_src->stream, pipe->stream))
552 		return false;
553 
554 	return true;
555 }
556 
557 struct clock_source *resource_find_used_clk_src_for_sharing(
558 					struct resource_context *res_ctx,
559 					struct pipe_ctx *pipe_ctx)
560 {
561 	int i;
562 
563 	for (i = 0; i < MAX_PIPES; i++) {
564 		if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
565 			return res_ctx->pipe_ctx[i].clock_source;
566 	}
567 
568 	return NULL;
569 }
570 
571 static enum pixel_format convert_pixel_format_to_dalsurface(
572 		enum surface_pixel_format surface_pixel_format)
573 {
574 	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
575 
576 	switch (surface_pixel_format) {
577 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
578 		dal_pixel_format = PIXEL_FORMAT_INDEX8;
579 		break;
580 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
581 		dal_pixel_format = PIXEL_FORMAT_RGB565;
582 		break;
583 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
584 		dal_pixel_format = PIXEL_FORMAT_RGB565;
585 		break;
586 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
587 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
588 		break;
589 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
590 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
591 		break;
592 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
593 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
594 		break;
595 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
596 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
597 		break;
598 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
599 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
600 		break;
601 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
602 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
603 		dal_pixel_format = PIXEL_FORMAT_FP16;
604 		break;
605 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
606 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
607 		dal_pixel_format = PIXEL_FORMAT_420BPP8;
608 		break;
609 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
610 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
611 		dal_pixel_format = PIXEL_FORMAT_420BPP10;
612 		break;
613 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
614 	default:
615 		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
616 		break;
617 	}
618 	return dal_pixel_format;
619 }
620 
621 static inline void get_vp_scan_direction(
622 	enum dc_rotation_angle rotation,
623 	bool horizontal_mirror,
624 	bool *orthogonal_rotation,
625 	bool *flip_vert_scan_dir,
626 	bool *flip_horz_scan_dir)
627 {
628 	*orthogonal_rotation = false;
629 	*flip_vert_scan_dir = false;
630 	*flip_horz_scan_dir = false;
631 	if (rotation == ROTATION_ANGLE_180) {
632 		*flip_vert_scan_dir = true;
633 		*flip_horz_scan_dir = true;
634 	} else if (rotation == ROTATION_ANGLE_90) {
635 		*orthogonal_rotation = true;
636 		*flip_horz_scan_dir = true;
637 	} else if (rotation == ROTATION_ANGLE_270) {
638 		*orthogonal_rotation = true;
639 		*flip_vert_scan_dir = true;
640 	}
641 
642 	if (horizontal_mirror)
643 		*flip_horz_scan_dir = !*flip_horz_scan_dir;
644 }
645 
646 int get_num_mpc_splits(struct pipe_ctx *pipe)
647 {
648 	int mpc_split_count = 0;
649 	struct pipe_ctx *other_pipe = pipe->bottom_pipe;
650 
651 	while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
652 		mpc_split_count++;
653 		other_pipe = other_pipe->bottom_pipe;
654 	}
655 	other_pipe = pipe->top_pipe;
656 	while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
657 		mpc_split_count++;
658 		other_pipe = other_pipe->top_pipe;
659 	}
660 
661 	return mpc_split_count;
662 }
663 
664 int get_num_odm_splits(struct pipe_ctx *pipe)
665 {
666 	int odm_split_count = 0;
667 	struct pipe_ctx *next_pipe = pipe->next_odm_pipe;
668 	while (next_pipe) {
669 		odm_split_count++;
670 		next_pipe = next_pipe->next_odm_pipe;
671 	}
672 	pipe = pipe->prev_odm_pipe;
673 	while (pipe) {
674 		odm_split_count++;
675 		pipe = pipe->prev_odm_pipe;
676 	}
677 	return odm_split_count;
678 }
679 
680 static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx)
681 {
682 	*split_count = get_num_odm_splits(pipe_ctx);
683 	*split_idx = 0;
684 	if (*split_count == 0) {
685 		/*Check for mpc split*/
686 		struct pipe_ctx *split_pipe = pipe_ctx->top_pipe;
687 
688 		*split_count = get_num_mpc_splits(pipe_ctx);
689 		while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) {
690 			(*split_idx)++;
691 			split_pipe = split_pipe->top_pipe;
692 		}
693 	} else {
694 		/*Get odm split index*/
695 		struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe;
696 
697 		while (split_pipe) {
698 			(*split_idx)++;
699 			split_pipe = split_pipe->prev_odm_pipe;
700 		}
701 	}
702 }
703 
704 /*
705  * This is a preliminary vp size calculation to allow us to check taps support.
706  * The result is completely overridden afterwards.
707  */
708 static void calculate_viewport_size(struct pipe_ctx *pipe_ctx)
709 {
710 	struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
711 
712 	data->viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz, data->recout.width));
713 	data->viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert, data->recout.height));
714 	data->viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz_c, data->recout.width));
715 	data->viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert_c, data->recout.height));
716 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
717 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
718 		swap(data->viewport.width, data->viewport.height);
719 		swap(data->viewport_c.width, data->viewport_c.height);
720 	}
721 }
722 
723 static void calculate_recout(struct pipe_ctx *pipe_ctx)
724 {
725 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
726 	const struct dc_stream_state *stream = pipe_ctx->stream;
727 	struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
728 	struct rect surf_clip = plane_state->clip_rect;
729 	bool split_tb = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
730 	int split_count, split_idx;
731 
732 	calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
733 	if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
734 		split_idx = 0;
735 
736 	/*
737 	 * Only the leftmost ODM pipe should be offset by a nonzero distance
738 	 */
739 	if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) {
740 		data->recout.x = stream->dst.x;
741 		if (stream->src.x < surf_clip.x)
742 			data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width
743 						/ stream->src.width;
744 	} else
745 		data->recout.x = 0;
746 
747 	if (stream->src.x > surf_clip.x)
748 		surf_clip.width -= stream->src.x - surf_clip.x;
749 	data->recout.width = surf_clip.width * stream->dst.width / stream->src.width;
750 	if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width)
751 		data->recout.width = stream->dst.x + stream->dst.width - data->recout.x;
752 
753 	data->recout.y = stream->dst.y;
754 	if (stream->src.y < surf_clip.y)
755 		data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height
756 						/ stream->src.height;
757 	else if (stream->src.y > surf_clip.y)
758 		surf_clip.height -= stream->src.y - surf_clip.y;
759 
760 	data->recout.height = surf_clip.height * stream->dst.height / stream->src.height;
761 	if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height)
762 		data->recout.height = stream->dst.y + stream->dst.height - data->recout.y;
763 
764 	/* Handle h & v split */
765 	if (split_tb) {
766 		ASSERT(data->recout.height % 2 == 0);
767 		data->recout.height /= 2;
768 	} else if (split_count) {
769 		if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) {
770 			/* extra pixels in the division remainder need to go to pipes after
771 			 * the extra pixel index minus one(epimo) defined here as:
772 			 */
773 			int epimo = split_count - data->recout.width % (split_count + 1);
774 
775 			data->recout.x += (data->recout.width / (split_count + 1)) * split_idx;
776 			if (split_idx > epimo)
777 				data->recout.x += split_idx - epimo - 1;
778 			ASSERT(stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE || data->recout.width % 2 == 0);
779 			data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
780 		} else {
781 			/* odm */
782 			if (split_idx == split_count) {
783 				/* rightmost pipe is the remainder recout */
784 				data->recout.width -= data->h_active * split_count - data->recout.x;
785 				data->recout.x = 0;
786 			} else
787 				data->recout.width = data->h_active - data->recout.x;
788 		}
789 	}
790 }
791 
792 static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
793 {
794 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
795 	const struct dc_stream_state *stream = pipe_ctx->stream;
796 	struct rect surf_src = plane_state->src_rect;
797 	const int in_w = stream->src.width;
798 	const int in_h = stream->src.height;
799 	const int out_w = stream->dst.width;
800 	const int out_h = stream->dst.height;
801 
802 	/*Swap surf_src height and width since scaling ratios are in recout rotation*/
803 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
804 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
805 		swap(surf_src.height, surf_src.width);
806 
807 	pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction(
808 					surf_src.width,
809 					plane_state->dst_rect.width);
810 	pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction(
811 					surf_src.height,
812 					plane_state->dst_rect.height);
813 
814 	if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
815 		pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2;
816 	else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
817 		pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2;
818 
819 	pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64(
820 		pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h);
821 	pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64(
822 		pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w);
823 
824 	pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz;
825 	pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert;
826 
827 	if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8
828 			|| pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) {
829 		pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2;
830 		pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2;
831 	}
832 	pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate(
833 			pipe_ctx->plane_res.scl_data.ratios.horz, 19);
834 	pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate(
835 			pipe_ctx->plane_res.scl_data.ratios.vert, 19);
836 	pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate(
837 			pipe_ctx->plane_res.scl_data.ratios.horz_c, 19);
838 	pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate(
839 			pipe_ctx->plane_res.scl_data.ratios.vert_c, 19);
840 }
841 
842 
843 /*
844  * We completely calculate vp offset, size and inits here based entirely on scaling
845  * ratios and recout for pixel perfect pipe combine.
846  */
847 static void calculate_init_and_vp(
848 		bool flip_scan_dir,
849 		int recout_offset_within_recout_full,
850 		int recout_size,
851 		int src_size,
852 		int taps,
853 		struct fixed31_32 ratio,
854 		struct fixed31_32 *init,
855 		int *vp_offset,
856 		int *vp_size)
857 {
858 	struct fixed31_32 temp;
859 	int int_part;
860 
861 	/*
862 	 * First of the taps starts sampling pixel number <init_int_part> corresponding to recout
863 	 * pixel 1. Next recout pixel samples int part of <init + scaling ratio> and so on.
864 	 * All following calculations are based on this logic.
865 	 *
866 	 * Init calculated according to formula:
867 	 * 	init = (scaling_ratio + number_of_taps + 1) / 2
868 	 * 	init_bot = init + scaling_ratio
869 	 * 	to get pixel perfect combine add the fraction from calculating vp offset
870 	 */
871 	temp = dc_fixpt_mul_int(ratio, recout_offset_within_recout_full);
872 	*vp_offset = dc_fixpt_floor(temp);
873 	temp.value &= 0xffffffff;
874 	*init = dc_fixpt_truncate(dc_fixpt_add(dc_fixpt_div_int(
875 			dc_fixpt_add_int(ratio, taps + 1), 2), temp), 19);
876 	/*
877 	 * If viewport has non 0 offset and there are more taps than covered by init then
878 	 * we should decrease the offset and increase init so we are never sampling
879 	 * outside of viewport.
880 	 */
881 	int_part = dc_fixpt_floor(*init);
882 	if (int_part < taps) {
883 		int_part = taps - int_part;
884 		if (int_part > *vp_offset)
885 			int_part = *vp_offset;
886 		*vp_offset -= int_part;
887 		*init = dc_fixpt_add_int(*init, int_part);
888 	}
889 	/*
890 	 * If taps are sampling outside of viewport at end of recout and there are more pixels
891 	 * available in the surface we should increase the viewport size, regardless set vp to
892 	 * only what is used.
893 	 */
894 	temp = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_size - 1));
895 	*vp_size = dc_fixpt_floor(temp);
896 	if (*vp_size + *vp_offset > src_size)
897 		*vp_size = src_size - *vp_offset;
898 
899 	/* We did all the math assuming we are scanning same direction as display does,
900 	 * however mirror/rotation changes how vp scans vs how it is offset. If scan direction
901 	 * is flipped we simply need to calculate offset from the other side of plane.
902 	 * Note that outside of viewport all scaling hardware works in recout space.
903 	 */
904 	if (flip_scan_dir)
905 		*vp_offset = src_size - *vp_offset - *vp_size;
906 }
907 
908 static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx)
909 {
910 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
911 	const struct dc_stream_state *stream = pipe_ctx->stream;
912 	struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
913 	struct rect src = plane_state->src_rect;
914 	int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
915 				|| data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
916 	int split_count, split_idx, ro_lb, ro_tb, recout_full_x, recout_full_y;
917 	bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir;
918 
919 	calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
920 	/*
921 	 * recout full is what the recout would have been if we didnt clip
922 	 * the source plane at all. We only care about left(ro_lb) and top(ro_tb)
923 	 * offsets of recout within recout full because those are the directions
924 	 * we scan from and therefore the only ones that affect inits.
925 	 */
926 	recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
927 			* stream->dst.width / stream->src.width;
928 	recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
929 			* stream->dst.height / stream->src.height;
930 	if (pipe_ctx->prev_odm_pipe && split_idx)
931 		ro_lb = data->h_active * split_idx - recout_full_x;
932 	else
933 		ro_lb = data->recout.x - recout_full_x;
934 	ro_tb = data->recout.y - recout_full_y;
935 	ASSERT(ro_lb >= 0 && ro_tb >= 0);
936 
937 	/*
938 	 * Work in recout rotation since that requires less transformations
939 	 */
940 	get_vp_scan_direction(
941 			plane_state->rotation,
942 			plane_state->horizontal_mirror,
943 			&orthogonal_rotation,
944 			&flip_vert_scan_dir,
945 			&flip_horz_scan_dir);
946 
947 	if (orthogonal_rotation) {
948 		swap(src.width, src.height);
949 		swap(flip_vert_scan_dir, flip_horz_scan_dir);
950 	}
951 
952 	calculate_init_and_vp(
953 			flip_horz_scan_dir,
954 			ro_lb,
955 			data->recout.width,
956 			src.width,
957 			data->taps.h_taps,
958 			data->ratios.horz,
959 			&data->inits.h,
960 			&data->viewport.x,
961 			&data->viewport.width);
962 	calculate_init_and_vp(
963 			flip_horz_scan_dir,
964 			ro_lb,
965 			data->recout.width,
966 			src.width / vpc_div,
967 			data->taps.h_taps_c,
968 			data->ratios.horz_c,
969 			&data->inits.h_c,
970 			&data->viewport_c.x,
971 			&data->viewport_c.width);
972 	calculate_init_and_vp(
973 			flip_vert_scan_dir,
974 			ro_tb,
975 			data->recout.height,
976 			src.height,
977 			data->taps.v_taps,
978 			data->ratios.vert,
979 			&data->inits.v,
980 			&data->viewport.y,
981 			&data->viewport.height);
982 	calculate_init_and_vp(
983 			flip_vert_scan_dir,
984 			ro_tb,
985 			data->recout.height,
986 			src.height / vpc_div,
987 			data->taps.v_taps_c,
988 			data->ratios.vert_c,
989 			&data->inits.v_c,
990 			&data->viewport_c.y,
991 			&data->viewport_c.height);
992 	if (orthogonal_rotation) {
993 		swap(data->viewport.x, data->viewport.y);
994 		swap(data->viewport.width, data->viewport.height);
995 		swap(data->viewport_c.x, data->viewport_c.y);
996 		swap(data->viewport_c.width, data->viewport_c.height);
997 	}
998 	data->viewport.x += src.x;
999 	data->viewport.y += src.y;
1000 	ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0);
1001 	data->viewport_c.x += src.x / vpc_div;
1002 	data->viewport_c.y += src.y / vpc_div;
1003 }
1004 
1005 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
1006 {
1007 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1008 	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1009 	bool res = false;
1010 	DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
1011 
1012 	pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
1013 			pipe_ctx->plane_state->format);
1014 
1015 	/* Timing borders are part of vactive that we are also supposed to skip in addition
1016 	 * to any stream dst offset. Since dm logic assumes dst is in addressable
1017 	 * space we need to add the the left and top borders to dst offsets temporarily.
1018 	 * TODO: fix in DM, stream dst is supposed to be in vactive
1019 	 */
1020 	pipe_ctx->stream->dst.x += timing->h_border_left;
1021 	pipe_ctx->stream->dst.y += timing->v_border_top;
1022 
1023 	/* Calculate H and V active size */
1024 	pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable +
1025 			timing->h_border_left + timing->h_border_right;
1026 	pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable +
1027 		timing->v_border_top + timing->v_border_bottom;
1028 	if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe)
1029 		pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1;
1030 
1031 	/* depends on h_active */
1032 	calculate_recout(pipe_ctx);
1033 	/* depends on pixel format */
1034 	calculate_scaling_ratios(pipe_ctx);
1035 	/* depends on scaling ratios and recout, does not calculate offset yet */
1036 	calculate_viewport_size(pipe_ctx);
1037 
1038 	/*
1039 	 * LB calculations depend on vp size, h/v_active and scaling ratios
1040 	 * Setting line buffer pixel depth to 24bpp yields banding
1041 	 * on certain displays, such as the Sharp 4k
1042 	 */
1043 	pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
1044 	pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
1045 
1046 	if (pipe_ctx->plane_res.xfm != NULL)
1047 		res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
1048 				pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
1049 
1050 	if (pipe_ctx->plane_res.dpp != NULL)
1051 		res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
1052 				pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
1053 
1054 
1055 	if (!res) {
1056 		/* Try 24 bpp linebuffer */
1057 		pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
1058 
1059 		if (pipe_ctx->plane_res.xfm != NULL)
1060 			res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
1061 					pipe_ctx->plane_res.xfm,
1062 					&pipe_ctx->plane_res.scl_data,
1063 					&plane_state->scaling_quality);
1064 
1065 		if (pipe_ctx->plane_res.dpp != NULL)
1066 			res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
1067 					pipe_ctx->plane_res.dpp,
1068 					&pipe_ctx->plane_res.scl_data,
1069 					&plane_state->scaling_quality);
1070 	}
1071 
1072 	/*
1073 	 * Depends on recout, scaling ratios, h_active and taps
1074 	 * May need to re-check lb size after this in some obscure scenario
1075 	 */
1076 	if (res)
1077 		calculate_inits_and_viewports(pipe_ctx);
1078 
1079 	/*
1080 	 * Handle side by side and top bottom 3d recout offsets after vp calculation
1081 	 * since 3d is special and needs to calculate vp as if there is no recout offset
1082 	 * This may break with rotation, good thing we aren't mixing hw rotation and 3d
1083 	 */
1084 	if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == plane_state) {
1085 		ASSERT(plane_state->rotation == ROTATION_ANGLE_0 ||
1086 			(pipe_ctx->stream->view_format != VIEW_3D_FORMAT_TOP_AND_BOTTOM &&
1087 				pipe_ctx->stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE));
1088 		if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
1089 			pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height;
1090 		else if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
1091 			pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width;
1092 	}
1093 
1094 	if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
1095 			pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
1096 		res = false;
1097 
1098 	DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d  Recout: height:%d width:%d x:%d y:%d  HACTIVE:%d VACTIVE:%d\n"
1099 			"src_rect: height:%d width:%d x:%d y:%d  dst_rect: height:%d width:%d x:%d y:%d  clip_rect: height:%d width:%d x:%d y:%d\n",
1100 			__func__,
1101 			pipe_ctx->pipe_idx,
1102 			pipe_ctx->plane_res.scl_data.viewport.height,
1103 			pipe_ctx->plane_res.scl_data.viewport.width,
1104 			pipe_ctx->plane_res.scl_data.viewport.x,
1105 			pipe_ctx->plane_res.scl_data.viewport.y,
1106 			pipe_ctx->plane_res.scl_data.recout.height,
1107 			pipe_ctx->plane_res.scl_data.recout.width,
1108 			pipe_ctx->plane_res.scl_data.recout.x,
1109 			pipe_ctx->plane_res.scl_data.recout.y,
1110 			pipe_ctx->plane_res.scl_data.h_active,
1111 			pipe_ctx->plane_res.scl_data.v_active,
1112 			plane_state->src_rect.height,
1113 			plane_state->src_rect.width,
1114 			plane_state->src_rect.x,
1115 			plane_state->src_rect.y,
1116 			plane_state->dst_rect.height,
1117 			plane_state->dst_rect.width,
1118 			plane_state->dst_rect.x,
1119 			plane_state->dst_rect.y,
1120 			plane_state->clip_rect.height,
1121 			plane_state->clip_rect.width,
1122 			plane_state->clip_rect.x,
1123 			plane_state->clip_rect.y);
1124 
1125 	pipe_ctx->stream->dst.x -= timing->h_border_left;
1126 	pipe_ctx->stream->dst.y -= timing->v_border_top;
1127 
1128 	return res;
1129 }
1130 
1131 
1132 enum dc_status resource_build_scaling_params_for_context(
1133 	const struct dc  *dc,
1134 	struct dc_state *context)
1135 {
1136 	int i;
1137 
1138 	for (i = 0; i < MAX_PIPES; i++) {
1139 		if (context->res_ctx.pipe_ctx[i].plane_state != NULL &&
1140 				context->res_ctx.pipe_ctx[i].stream != NULL)
1141 			if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i]))
1142 				return DC_FAIL_SCALING;
1143 	}
1144 
1145 	return DC_OK;
1146 }
1147 
1148 struct pipe_ctx *find_idle_secondary_pipe(
1149 		struct resource_context *res_ctx,
1150 		const struct resource_pool *pool,
1151 		const struct pipe_ctx *primary_pipe)
1152 {
1153 	int i;
1154 	struct pipe_ctx *secondary_pipe = NULL;
1155 
1156 	/*
1157 	 * We add a preferred pipe mapping to avoid the chance that
1158 	 * MPCCs already in use will need to be reassigned to other trees.
1159 	 * For example, if we went with the strict, assign backwards logic:
1160 	 *
1161 	 * (State 1)
1162 	 * Display A on, no surface, top pipe = 0
1163 	 * Display B on, no surface, top pipe = 1
1164 	 *
1165 	 * (State 2)
1166 	 * Display A on, no surface, top pipe = 0
1167 	 * Display B on, surface enable, top pipe = 1, bottom pipe = 5
1168 	 *
1169 	 * (State 3)
1170 	 * Display A on, surface enable, top pipe = 0, bottom pipe = 5
1171 	 * Display B on, surface enable, top pipe = 1, bottom pipe = 4
1172 	 *
1173 	 * The state 2->3 transition requires remapping MPCC 5 from display B
1174 	 * to display A.
1175 	 *
1176 	 * However, with the preferred pipe logic, state 2 would look like:
1177 	 *
1178 	 * (State 2)
1179 	 * Display A on, no surface, top pipe = 0
1180 	 * Display B on, surface enable, top pipe = 1, bottom pipe = 4
1181 	 *
1182 	 * This would then cause 2->3 to not require remapping any MPCCs.
1183 	 */
1184 	if (primary_pipe) {
1185 		int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
1186 		if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
1187 			secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
1188 			secondary_pipe->pipe_idx = preferred_pipe_idx;
1189 		}
1190 	}
1191 
1192 	/*
1193 	 * search backwards for the second pipe to keep pipe
1194 	 * assignment more consistent
1195 	 */
1196 	if (!secondary_pipe)
1197 		for (i = pool->pipe_count - 1; i >= 0; i--) {
1198 			if (res_ctx->pipe_ctx[i].stream == NULL) {
1199 				secondary_pipe = &res_ctx->pipe_ctx[i];
1200 				secondary_pipe->pipe_idx = i;
1201 				break;
1202 			}
1203 		}
1204 
1205 	return secondary_pipe;
1206 }
1207 
1208 struct pipe_ctx *resource_get_head_pipe_for_stream(
1209 		struct resource_context *res_ctx,
1210 		struct dc_stream_state *stream)
1211 {
1212 	int i;
1213 
1214 	for (i = 0; i < MAX_PIPES; i++) {
1215 		if (res_ctx->pipe_ctx[i].stream == stream
1216 				&& !res_ctx->pipe_ctx[i].top_pipe
1217 				&& !res_ctx->pipe_ctx[i].prev_odm_pipe)
1218 			return &res_ctx->pipe_ctx[i];
1219 	}
1220 	return NULL;
1221 }
1222 
1223 static struct pipe_ctx *resource_get_tail_pipe(
1224 		struct resource_context *res_ctx,
1225 		struct pipe_ctx *head_pipe)
1226 {
1227 	struct pipe_ctx *tail_pipe;
1228 
1229 	tail_pipe = head_pipe->bottom_pipe;
1230 
1231 	while (tail_pipe) {
1232 		head_pipe = tail_pipe;
1233 		tail_pipe = tail_pipe->bottom_pipe;
1234 	}
1235 
1236 	return head_pipe;
1237 }
1238 
1239 /*
1240  * A free_pipe for a stream is defined here as a pipe
1241  * that has no surface attached yet
1242  */
1243 static struct pipe_ctx *acquire_free_pipe_for_head(
1244 		struct dc_state *context,
1245 		const struct resource_pool *pool,
1246 		struct pipe_ctx *head_pipe)
1247 {
1248 	int i;
1249 	struct resource_context *res_ctx = &context->res_ctx;
1250 
1251 	if (!head_pipe->plane_state)
1252 		return head_pipe;
1253 
1254 	/* Re-use pipe already acquired for this stream if available*/
1255 	for (i = pool->pipe_count - 1; i >= 0; i--) {
1256 		if (res_ctx->pipe_ctx[i].stream == head_pipe->stream &&
1257 				!res_ctx->pipe_ctx[i].plane_state) {
1258 			return &res_ctx->pipe_ctx[i];
1259 		}
1260 	}
1261 
1262 	/*
1263 	 * At this point we have no re-useable pipe for this stream and we need
1264 	 * to acquire an idle one to satisfy the request
1265 	 */
1266 
1267 	if (!pool->funcs->acquire_idle_pipe_for_layer)
1268 		return NULL;
1269 
1270 	return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream);
1271 }
1272 
1273 #if defined(CONFIG_DRM_AMD_DC_DCN)
1274 static int acquire_first_split_pipe(
1275 		struct resource_context *res_ctx,
1276 		const struct resource_pool *pool,
1277 		struct dc_stream_state *stream)
1278 {
1279 	int i;
1280 
1281 	for (i = 0; i < pool->pipe_count; i++) {
1282 		struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i];
1283 
1284 		if (split_pipe->top_pipe &&
1285 				split_pipe->top_pipe->plane_state == split_pipe->plane_state) {
1286 			split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe;
1287 			if (split_pipe->bottom_pipe)
1288 				split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe;
1289 
1290 			if (split_pipe->top_pipe->plane_state)
1291 				resource_build_scaling_params(split_pipe->top_pipe);
1292 
1293 			memset(split_pipe, 0, sizeof(*split_pipe));
1294 			split_pipe->stream_res.tg = pool->timing_generators[i];
1295 			split_pipe->plane_res.hubp = pool->hubps[i];
1296 			split_pipe->plane_res.ipp = pool->ipps[i];
1297 			split_pipe->plane_res.dpp = pool->dpps[i];
1298 			split_pipe->stream_res.opp = pool->opps[i];
1299 			split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst;
1300 			split_pipe->pipe_idx = i;
1301 
1302 			split_pipe->stream = stream;
1303 			return i;
1304 		}
1305 	}
1306 	return -1;
1307 }
1308 #endif
1309 
1310 bool dc_add_plane_to_context(
1311 		const struct dc *dc,
1312 		struct dc_stream_state *stream,
1313 		struct dc_plane_state *plane_state,
1314 		struct dc_state *context)
1315 {
1316 	int i;
1317 	struct resource_pool *pool = dc->res_pool;
1318 	struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe;
1319 	struct dc_stream_status *stream_status = NULL;
1320 
1321 	for (i = 0; i < context->stream_count; i++)
1322 		if (context->streams[i] == stream) {
1323 			stream_status = &context->stream_status[i];
1324 			break;
1325 		}
1326 	if (stream_status == NULL) {
1327 		dm_error("Existing stream not found; failed to attach surface!\n");
1328 		return false;
1329 	}
1330 
1331 
1332 	if (stream_status->plane_count == MAX_SURFACE_NUM) {
1333 		dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
1334 				plane_state, MAX_SURFACE_NUM);
1335 		return false;
1336 	}
1337 
1338 	head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream);
1339 
1340 	if (!head_pipe) {
1341 		dm_error("Head pipe not found for stream_state %p !\n", stream);
1342 		return false;
1343 	}
1344 
1345 	/* retain new surface, but only once per stream */
1346 	dc_plane_state_retain(plane_state);
1347 
1348 	while (head_pipe) {
1349 		free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe);
1350 
1351 	#if defined(CONFIG_DRM_AMD_DC_DCN)
1352 		if (!free_pipe) {
1353 			int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
1354 			if (pipe_idx >= 0)
1355 				free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
1356 		}
1357 	#endif
1358 		if (!free_pipe) {
1359 			dc_plane_state_release(plane_state);
1360 			return false;
1361 		}
1362 
1363 		free_pipe->plane_state = plane_state;
1364 
1365 		if (head_pipe != free_pipe) {
1366 			tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe);
1367 			ASSERT(tail_pipe);
1368 			free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
1369 			free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
1370 			free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
1371 			free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
1372 			free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
1373 			free_pipe->clock_source = tail_pipe->clock_source;
1374 			free_pipe->top_pipe = tail_pipe;
1375 			tail_pipe->bottom_pipe = free_pipe;
1376 			if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) {
1377 				free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe;
1378 				tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe;
1379 			}
1380 			if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) {
1381 				free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe;
1382 				tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe;
1383 			}
1384 		}
1385 		head_pipe = head_pipe->next_odm_pipe;
1386 	}
1387 	/* assign new surfaces*/
1388 	stream_status->plane_states[stream_status->plane_count] = plane_state;
1389 
1390 	stream_status->plane_count++;
1391 
1392 	return true;
1393 }
1394 
1395 bool dc_remove_plane_from_context(
1396 		const struct dc *dc,
1397 		struct dc_stream_state *stream,
1398 		struct dc_plane_state *plane_state,
1399 		struct dc_state *context)
1400 {
1401 	int i;
1402 	struct dc_stream_status *stream_status = NULL;
1403 	struct resource_pool *pool = dc->res_pool;
1404 
1405 	for (i = 0; i < context->stream_count; i++)
1406 		if (context->streams[i] == stream) {
1407 			stream_status = &context->stream_status[i];
1408 			break;
1409 		}
1410 
1411 	if (stream_status == NULL) {
1412 		dm_error("Existing stream not found; failed to remove plane.\n");
1413 		return false;
1414 	}
1415 
1416 	/* release pipe for plane*/
1417 	for (i = pool->pipe_count - 1; i >= 0; i--) {
1418 		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1419 
1420 		if (pipe_ctx->plane_state == plane_state) {
1421 			if (pipe_ctx->top_pipe)
1422 				pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
1423 
1424 			/* Second condition is to avoid setting NULL to top pipe
1425 			 * of tail pipe making it look like head pipe in subsequent
1426 			 * deletes
1427 			 */
1428 			if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe)
1429 				pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
1430 
1431 			/*
1432 			 * For head pipe detach surfaces from pipe for tail
1433 			 * pipe just zero it out
1434 			 */
1435 			if (!pipe_ctx->top_pipe)
1436 				pipe_ctx->plane_state = NULL;
1437 			else
1438 				memset(pipe_ctx, 0, sizeof(*pipe_ctx));
1439 		}
1440 	}
1441 
1442 
1443 	for (i = 0; i < stream_status->plane_count; i++) {
1444 		if (stream_status->plane_states[i] == plane_state) {
1445 
1446 			dc_plane_state_release(stream_status->plane_states[i]);
1447 			break;
1448 		}
1449 	}
1450 
1451 	if (i == stream_status->plane_count) {
1452 		dm_error("Existing plane_state not found; failed to detach it!\n");
1453 		return false;
1454 	}
1455 
1456 	stream_status->plane_count--;
1457 
1458 	/* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */
1459 	for (; i < stream_status->plane_count; i++)
1460 		stream_status->plane_states[i] = stream_status->plane_states[i + 1];
1461 
1462 	stream_status->plane_states[stream_status->plane_count] = NULL;
1463 
1464 	return true;
1465 }
1466 
1467 bool dc_rem_all_planes_for_stream(
1468 		const struct dc *dc,
1469 		struct dc_stream_state *stream,
1470 		struct dc_state *context)
1471 {
1472 	int i, old_plane_count;
1473 	struct dc_stream_status *stream_status = NULL;
1474 	struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
1475 
1476 	for (i = 0; i < context->stream_count; i++)
1477 			if (context->streams[i] == stream) {
1478 				stream_status = &context->stream_status[i];
1479 				break;
1480 			}
1481 
1482 	if (stream_status == NULL) {
1483 		dm_error("Existing stream %p not found!\n", stream);
1484 		return false;
1485 	}
1486 
1487 	old_plane_count = stream_status->plane_count;
1488 
1489 	for (i = 0; i < old_plane_count; i++)
1490 		del_planes[i] = stream_status->plane_states[i];
1491 
1492 	for (i = 0; i < old_plane_count; i++)
1493 		if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context))
1494 			return false;
1495 
1496 	return true;
1497 }
1498 
1499 static bool add_all_planes_for_stream(
1500 		const struct dc *dc,
1501 		struct dc_stream_state *stream,
1502 		const struct dc_validation_set set[],
1503 		int set_count,
1504 		struct dc_state *context)
1505 {
1506 	int i, j;
1507 
1508 	for (i = 0; i < set_count; i++)
1509 		if (set[i].stream == stream)
1510 			break;
1511 
1512 	if (i == set_count) {
1513 		dm_error("Stream %p not found in set!\n", stream);
1514 		return false;
1515 	}
1516 
1517 	for (j = 0; j < set[i].plane_count; j++)
1518 		if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context))
1519 			return false;
1520 
1521 	return true;
1522 }
1523 
1524 bool dc_add_all_planes_for_stream(
1525 		const struct dc *dc,
1526 		struct dc_stream_state *stream,
1527 		struct dc_plane_state * const *plane_states,
1528 		int plane_count,
1529 		struct dc_state *context)
1530 {
1531 	struct dc_validation_set set;
1532 	int i;
1533 
1534 	set.stream = stream;
1535 	set.plane_count = plane_count;
1536 
1537 	for (i = 0; i < plane_count; i++)
1538 		set.plane_states[i] = plane_states[i];
1539 
1540 	return add_all_planes_for_stream(dc, stream, &set, 1, context);
1541 }
1542 
1543 static bool is_timing_changed(struct dc_stream_state *cur_stream,
1544 		struct dc_stream_state *new_stream)
1545 {
1546 	if (cur_stream == NULL)
1547 		return true;
1548 
1549 	/* If output color space is changed, need to reprogram info frames */
1550 	if (cur_stream->output_color_space != new_stream->output_color_space)
1551 		return true;
1552 
1553 	return memcmp(
1554 		&cur_stream->timing,
1555 		&new_stream->timing,
1556 		sizeof(struct dc_crtc_timing)) != 0;
1557 }
1558 
1559 static bool are_stream_backends_same(
1560 	struct dc_stream_state *stream_a, struct dc_stream_state *stream_b)
1561 {
1562 	if (stream_a == stream_b)
1563 		return true;
1564 
1565 	if (stream_a == NULL || stream_b == NULL)
1566 		return false;
1567 
1568 	if (is_timing_changed(stream_a, stream_b))
1569 		return false;
1570 
1571 	if (stream_a->dpms_off != stream_b->dpms_off)
1572 		return false;
1573 
1574 	return true;
1575 }
1576 
1577 /*
1578  * dc_is_stream_unchanged() - Compare two stream states for equivalence.
1579  *
1580  * Checks if there a difference between the two states
1581  * that would require a mode change.
1582  *
1583  * Does not compare cursor position or attributes.
1584  */
1585 bool dc_is_stream_unchanged(
1586 	struct dc_stream_state *old_stream, struct dc_stream_state *stream)
1587 {
1588 
1589 	if (!are_stream_backends_same(old_stream, stream))
1590 		return false;
1591 
1592 	if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param)
1593 		return false;
1594 
1595 	return true;
1596 }
1597 
1598 /*
1599  * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams.
1600  */
1601 bool dc_is_stream_scaling_unchanged(
1602 	struct dc_stream_state *old_stream, struct dc_stream_state *stream)
1603 {
1604 	if (old_stream == stream)
1605 		return true;
1606 
1607 	if (old_stream == NULL || stream == NULL)
1608 		return false;
1609 
1610 	if (memcmp(&old_stream->src,
1611 			&stream->src,
1612 			sizeof(struct rect)) != 0)
1613 		return false;
1614 
1615 	if (memcmp(&old_stream->dst,
1616 			&stream->dst,
1617 			sizeof(struct rect)) != 0)
1618 		return false;
1619 
1620 	return true;
1621 }
1622 
1623 static void update_stream_engine_usage(
1624 		struct resource_context *res_ctx,
1625 		const struct resource_pool *pool,
1626 		struct stream_encoder *stream_enc,
1627 		bool acquired)
1628 {
1629 	int i;
1630 
1631 	for (i = 0; i < pool->stream_enc_count; i++) {
1632 		if (pool->stream_enc[i] == stream_enc)
1633 			res_ctx->is_stream_enc_acquired[i] = acquired;
1634 	}
1635 }
1636 
1637 /* TODO: release audio object */
1638 void update_audio_usage(
1639 		struct resource_context *res_ctx,
1640 		const struct resource_pool *pool,
1641 		struct audio *audio,
1642 		bool acquired)
1643 {
1644 	int i;
1645 	for (i = 0; i < pool->audio_count; i++) {
1646 		if (pool->audios[i] == audio)
1647 			res_ctx->is_audio_acquired[i] = acquired;
1648 	}
1649 }
1650 
1651 static int acquire_first_free_pipe(
1652 		struct resource_context *res_ctx,
1653 		const struct resource_pool *pool,
1654 		struct dc_stream_state *stream)
1655 {
1656 	int i;
1657 
1658 	for (i = 0; i < pool->pipe_count; i++) {
1659 		if (!res_ctx->pipe_ctx[i].stream) {
1660 			struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1661 
1662 			pipe_ctx->stream_res.tg = pool->timing_generators[i];
1663 			pipe_ctx->plane_res.mi = pool->mis[i];
1664 			pipe_ctx->plane_res.hubp = pool->hubps[i];
1665 			pipe_ctx->plane_res.ipp = pool->ipps[i];
1666 			pipe_ctx->plane_res.xfm = pool->transforms[i];
1667 			pipe_ctx->plane_res.dpp = pool->dpps[i];
1668 			pipe_ctx->stream_res.opp = pool->opps[i];
1669 			if (pool->dpps[i])
1670 				pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst;
1671 			pipe_ctx->pipe_idx = i;
1672 
1673 
1674 			pipe_ctx->stream = stream;
1675 			return i;
1676 		}
1677 	}
1678 	return -1;
1679 }
1680 
1681 static struct audio *find_first_free_audio(
1682 		struct resource_context *res_ctx,
1683 		const struct resource_pool *pool,
1684 		enum engine_id id,
1685 		enum dce_version dc_version)
1686 {
1687 	int i, available_audio_count;
1688 
1689 	available_audio_count = pool->audio_count;
1690 
1691 	for (i = 0; i < available_audio_count; i++) {
1692 		if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) {
1693 			/*we have enough audio endpoint, find the matching inst*/
1694 			if (id != i)
1695 				continue;
1696 			return pool->audios[i];
1697 		}
1698 	}
1699 
1700 	/* use engine id to find free audio */
1701 	if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) {
1702 		return pool->audios[id];
1703 	}
1704 	/*not found the matching one, first come first serve*/
1705 	for (i = 0; i < available_audio_count; i++) {
1706 		if (res_ctx->is_audio_acquired[i] == false) {
1707 			return pool->audios[i];
1708 		}
1709 	}
1710 	return 0;
1711 }
1712 
1713 /*
1714  * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state.
1715  */
1716 enum dc_status dc_add_stream_to_ctx(
1717 		struct dc *dc,
1718 		struct dc_state *new_ctx,
1719 		struct dc_stream_state *stream)
1720 {
1721 	enum dc_status res;
1722 	DC_LOGGER_INIT(dc->ctx->logger);
1723 
1724 	if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) {
1725 		DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream);
1726 		return DC_ERROR_UNEXPECTED;
1727 	}
1728 
1729 	new_ctx->streams[new_ctx->stream_count] = stream;
1730 	dc_stream_retain(stream);
1731 	new_ctx->stream_count++;
1732 
1733 	res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
1734 	if (res != DC_OK)
1735 		DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res);
1736 
1737 	return res;
1738 }
1739 
1740 /*
1741  * dc_remove_stream_from_ctx() - Remove a stream from a dc_state.
1742  */
1743 enum dc_status dc_remove_stream_from_ctx(
1744 			struct dc *dc,
1745 			struct dc_state *new_ctx,
1746 			struct dc_stream_state *stream)
1747 {
1748 	int i;
1749 	struct dc_context *dc_ctx = dc->ctx;
1750 	struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream);
1751 	struct pipe_ctx *odm_pipe;
1752 
1753 	if (!del_pipe) {
1754 		DC_ERROR("Pipe not found for stream %p !\n", stream);
1755 		return DC_ERROR_UNEXPECTED;
1756 	}
1757 
1758 	odm_pipe = del_pipe->next_odm_pipe;
1759 
1760 	/* Release primary pipe */
1761 	ASSERT(del_pipe->stream_res.stream_enc);
1762 	update_stream_engine_usage(
1763 			&new_ctx->res_ctx,
1764 				dc->res_pool,
1765 			del_pipe->stream_res.stream_enc,
1766 			false);
1767 	/* Release link encoder from stream in new dc_state. */
1768 	if (dc->res_pool->funcs->link_enc_unassign)
1769 		dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream);
1770 
1771 	if (del_pipe->stream_res.audio)
1772 		update_audio_usage(
1773 			&new_ctx->res_ctx,
1774 			dc->res_pool,
1775 			del_pipe->stream_res.audio,
1776 			false);
1777 
1778 	resource_unreference_clock_source(&new_ctx->res_ctx,
1779 					  dc->res_pool,
1780 					  del_pipe->clock_source);
1781 
1782 	if (dc->res_pool->funcs->remove_stream_from_ctx)
1783 		dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
1784 
1785 	while (odm_pipe) {
1786 		struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
1787 
1788 		memset(odm_pipe, 0, sizeof(*odm_pipe));
1789 		odm_pipe = next_odm_pipe;
1790 	}
1791 	memset(del_pipe, 0, sizeof(*del_pipe));
1792 
1793 	for (i = 0; i < new_ctx->stream_count; i++)
1794 		if (new_ctx->streams[i] == stream)
1795 			break;
1796 
1797 	if (new_ctx->streams[i] != stream) {
1798 		DC_ERROR("Context doesn't have stream %p !\n", stream);
1799 		return DC_ERROR_UNEXPECTED;
1800 	}
1801 
1802 	dc_stream_release(new_ctx->streams[i]);
1803 	new_ctx->stream_count--;
1804 
1805 	/* Trim back arrays */
1806 	for (; i < new_ctx->stream_count; i++) {
1807 		new_ctx->streams[i] = new_ctx->streams[i + 1];
1808 		new_ctx->stream_status[i] = new_ctx->stream_status[i + 1];
1809 	}
1810 
1811 	new_ctx->streams[new_ctx->stream_count] = NULL;
1812 	memset(
1813 			&new_ctx->stream_status[new_ctx->stream_count],
1814 			0,
1815 			sizeof(new_ctx->stream_status[0]));
1816 
1817 	return DC_OK;
1818 }
1819 
1820 static struct dc_stream_state *find_pll_sharable_stream(
1821 		struct dc_stream_state *stream_needs_pll,
1822 		struct dc_state *context)
1823 {
1824 	int i;
1825 
1826 	for (i = 0; i < context->stream_count; i++) {
1827 		struct dc_stream_state *stream_has_pll = context->streams[i];
1828 
1829 		/* We are looking for non dp, non virtual stream */
1830 		if (resource_are_streams_timing_synchronizable(
1831 			stream_needs_pll, stream_has_pll)
1832 			&& !dc_is_dp_signal(stream_has_pll->signal)
1833 			&& stream_has_pll->link->connector_signal
1834 			!= SIGNAL_TYPE_VIRTUAL)
1835 			return stream_has_pll;
1836 
1837 	}
1838 
1839 	return NULL;
1840 }
1841 
1842 static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
1843 {
1844 	uint32_t pix_clk = timing->pix_clk_100hz;
1845 	uint32_t normalized_pix_clk = pix_clk;
1846 
1847 	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
1848 		pix_clk /= 2;
1849 	if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
1850 		switch (timing->display_color_depth) {
1851 		case COLOR_DEPTH_666:
1852 		case COLOR_DEPTH_888:
1853 			normalized_pix_clk = pix_clk;
1854 			break;
1855 		case COLOR_DEPTH_101010:
1856 			normalized_pix_clk = (pix_clk * 30) / 24;
1857 			break;
1858 		case COLOR_DEPTH_121212:
1859 			normalized_pix_clk = (pix_clk * 36) / 24;
1860 		break;
1861 		case COLOR_DEPTH_161616:
1862 			normalized_pix_clk = (pix_clk * 48) / 24;
1863 		break;
1864 		default:
1865 			ASSERT(0);
1866 		break;
1867 		}
1868 	}
1869 	return normalized_pix_clk;
1870 }
1871 
1872 static void calculate_phy_pix_clks(struct dc_stream_state *stream)
1873 {
1874 	/* update actual pixel clock on all streams */
1875 	if (dc_is_hdmi_signal(stream->signal))
1876 		stream->phy_pix_clk = get_norm_pix_clk(
1877 			&stream->timing) / 10;
1878 	else
1879 		stream->phy_pix_clk =
1880 			stream->timing.pix_clk_100hz / 10;
1881 
1882 	if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
1883 		stream->phy_pix_clk *= 2;
1884 }
1885 
1886 static int acquire_resource_from_hw_enabled_state(
1887 		struct resource_context *res_ctx,
1888 		const struct resource_pool *pool,
1889 		struct dc_stream_state *stream)
1890 {
1891 	struct dc_link *link = stream->link;
1892 	unsigned int i, inst, tg_inst = 0;
1893 
1894 	/* Check for enabled DIG to identify enabled display */
1895 	if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
1896 		return -1;
1897 
1898 	inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
1899 
1900 	if (inst == ENGINE_ID_UNKNOWN)
1901 		return -1;
1902 
1903 	for (i = 0; i < pool->stream_enc_count; i++) {
1904 		if (pool->stream_enc[i]->id == inst) {
1905 			tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
1906 				pool->stream_enc[i]);
1907 			break;
1908 		}
1909 	}
1910 
1911 	// tg_inst not found
1912 	if (i == pool->stream_enc_count)
1913 		return -1;
1914 
1915 	if (tg_inst >= pool->timing_generator_count)
1916 		return -1;
1917 
1918 	if (!res_ctx->pipe_ctx[tg_inst].stream) {
1919 		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst];
1920 
1921 		pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
1922 		pipe_ctx->plane_res.mi = pool->mis[tg_inst];
1923 		pipe_ctx->plane_res.hubp = pool->hubps[tg_inst];
1924 		pipe_ctx->plane_res.ipp = pool->ipps[tg_inst];
1925 		pipe_ctx->plane_res.xfm = pool->transforms[tg_inst];
1926 		pipe_ctx->plane_res.dpp = pool->dpps[tg_inst];
1927 		pipe_ctx->stream_res.opp = pool->opps[tg_inst];
1928 
1929 		if (pool->dpps[tg_inst]) {
1930 			pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst;
1931 
1932 			// Read DPP->MPCC->OPP Pipe from HW State
1933 			if (pool->mpc->funcs->read_mpcc_state) {
1934 				struct mpcc_state s = {0};
1935 
1936 				pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s);
1937 
1938 				if (s.dpp_id < MAX_MPCC)
1939 					pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id;
1940 
1941 				if (s.bot_mpcc_id < MAX_MPCC)
1942 					pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot =
1943 							&pool->mpc->mpcc_array[s.bot_mpcc_id];
1944 
1945 				if (s.opp_id < MAX_OPP)
1946 					pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id;
1947 			}
1948 		}
1949 		pipe_ctx->pipe_idx = tg_inst;
1950 
1951 		pipe_ctx->stream = stream;
1952 		return tg_inst;
1953 	}
1954 
1955 	return -1;
1956 }
1957 
1958 static void mark_seamless_boot_stream(
1959 		const struct dc  *dc,
1960 		struct dc_stream_state *stream)
1961 {
1962 	struct dc_bios *dcb = dc->ctx->dc_bios;
1963 
1964 	/* TODO: Check Linux */
1965 	if (dc->config.allow_seamless_boot_optimization &&
1966 			!dcb->funcs->is_accelerated_mode(dcb)) {
1967 		if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing))
1968 			stream->apply_seamless_boot_optimization = true;
1969 	}
1970 }
1971 
1972 enum dc_status resource_map_pool_resources(
1973 		const struct dc  *dc,
1974 		struct dc_state *context,
1975 		struct dc_stream_state *stream)
1976 {
1977 	const struct resource_pool *pool = dc->res_pool;
1978 	int i;
1979 	struct dc_context *dc_ctx = dc->ctx;
1980 	struct pipe_ctx *pipe_ctx = NULL;
1981 	int pipe_idx = -1;
1982 
1983 	calculate_phy_pix_clks(stream);
1984 
1985 	mark_seamless_boot_stream(dc, stream);
1986 
1987 	if (stream->apply_seamless_boot_optimization) {
1988 		pipe_idx = acquire_resource_from_hw_enabled_state(
1989 				&context->res_ctx,
1990 				pool,
1991 				stream);
1992 		if (pipe_idx < 0)
1993 			/* hw resource was assigned to other stream */
1994 			stream->apply_seamless_boot_optimization = false;
1995 	}
1996 
1997 	if (pipe_idx < 0)
1998 		/* acquire new resources */
1999 		pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
2000 
2001 #ifdef CONFIG_DRM_AMD_DC_DCN
2002 	if (pipe_idx < 0)
2003 		pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
2004 #endif
2005 
2006 	if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL)
2007 		return DC_NO_CONTROLLER_RESOURCE;
2008 
2009 	pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
2010 
2011 	pipe_ctx->stream_res.stream_enc =
2012 		dc->res_pool->funcs->find_first_free_match_stream_enc_for_link(
2013 			&context->res_ctx, pool, stream);
2014 
2015 	if (!pipe_ctx->stream_res.stream_enc)
2016 		return DC_NO_STREAM_ENC_RESOURCE;
2017 
2018 	update_stream_engine_usage(
2019 		&context->res_ctx, pool,
2020 		pipe_ctx->stream_res.stream_enc,
2021 		true);
2022 
2023 	/* TODO: Add check if ASIC support and EDID audio */
2024 	if (!stream->converter_disable_audio &&
2025 	    dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
2026 	    stream->audio_info.mode_count && stream->audio_info.flags.all) {
2027 		pipe_ctx->stream_res.audio = find_first_free_audio(
2028 		&context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version);
2029 
2030 		/*
2031 		 * Audio assigned in order first come first get.
2032 		 * There are asics which has number of audio
2033 		 * resources less then number of pipes
2034 		 */
2035 		if (pipe_ctx->stream_res.audio)
2036 			update_audio_usage(&context->res_ctx, pool,
2037 					   pipe_ctx->stream_res.audio, true);
2038 	}
2039 
2040 	/* Add ABM to the resource if on EDP */
2041 	if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) {
2042 #if defined(CONFIG_DRM_AMD_DC_DCN)
2043 		if (pool->abm)
2044 			pipe_ctx->stream_res.abm = pool->abm;
2045 		else
2046 			pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst];
2047 #else
2048 		pipe_ctx->stream_res.abm = pool->abm;
2049 #endif
2050 	}
2051 
2052 	for (i = 0; i < context->stream_count; i++)
2053 		if (context->streams[i] == stream) {
2054 			context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
2055 			context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst;
2056 			context->stream_status[i].audio_inst =
2057 				pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1;
2058 
2059 			return DC_OK;
2060 		}
2061 
2062 	DC_ERROR("Stream %p not found in new ctx!\n", stream);
2063 	return DC_ERROR_UNEXPECTED;
2064 }
2065 
2066 /**
2067  * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state
2068  * Is a shallow copy.  Increments refcounts on existing streams and planes.
2069  * @dc: copy out of dc->current_state
2070  * @dst_ctx: copy into this
2071  */
2072 void dc_resource_state_copy_construct_current(
2073 		const struct dc *dc,
2074 		struct dc_state *dst_ctx)
2075 {
2076 	dc_resource_state_copy_construct(dc->current_state, dst_ctx);
2077 }
2078 
2079 
2080 void dc_resource_state_construct(
2081 		const struct dc *dc,
2082 		struct dc_state *dst_ctx)
2083 {
2084 	dst_ctx->clk_mgr = dc->clk_mgr;
2085 }
2086 
2087 
2088 bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
2089 {
2090 	return dc->res_pool->res_cap->num_dsc > 0;
2091 }
2092 
2093 
2094 /**
2095  * dc_validate_global_state() - Determine if HW can support a given state
2096  * Checks HW resource availability and bandwidth requirement.
2097  * @dc: dc struct for this driver
2098  * @new_ctx: state to be validated
2099  * @fast_validate: set to true if only yes/no to support matters
2100  *
2101  * Return: DC_OK if the result can be programmed.  Otherwise, an error code.
2102  */
2103 enum dc_status dc_validate_global_state(
2104 		struct dc *dc,
2105 		struct dc_state *new_ctx,
2106 		bool fast_validate)
2107 {
2108 	enum dc_status result = DC_ERROR_UNEXPECTED;
2109 	int i, j;
2110 
2111 	if (!new_ctx)
2112 		return DC_ERROR_UNEXPECTED;
2113 
2114 	if (dc->res_pool->funcs->validate_global) {
2115 		result = dc->res_pool->funcs->validate_global(dc, new_ctx);
2116 		if (result != DC_OK)
2117 			return result;
2118 	}
2119 
2120 	for (i = 0; i < new_ctx->stream_count; i++) {
2121 		struct dc_stream_state *stream = new_ctx->streams[i];
2122 
2123 		for (j = 0; j < dc->res_pool->pipe_count; j++) {
2124 			struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j];
2125 
2126 			if (pipe_ctx->stream != stream)
2127 				continue;
2128 
2129 			if (dc->res_pool->funcs->patch_unknown_plane_state &&
2130 					pipe_ctx->plane_state &&
2131 					pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
2132 				result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state);
2133 				if (result != DC_OK)
2134 					return result;
2135 			}
2136 
2137 			/* Switch to dp clock source only if there is
2138 			 * no non dp stream that shares the same timing
2139 			 * with the dp stream.
2140 			 */
2141 			if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
2142 				!find_pll_sharable_stream(stream, new_ctx)) {
2143 
2144 				resource_unreference_clock_source(
2145 						&new_ctx->res_ctx,
2146 						dc->res_pool,
2147 						pipe_ctx->clock_source);
2148 
2149 				pipe_ctx->clock_source = dc->res_pool->dp_clock_source;
2150 				resource_reference_clock_source(
2151 						&new_ctx->res_ctx,
2152 						dc->res_pool,
2153 						 pipe_ctx->clock_source);
2154 			}
2155 		}
2156 	}
2157 
2158 	result = resource_build_scaling_params_for_context(dc, new_ctx);
2159 
2160 	if (result == DC_OK)
2161 		if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate))
2162 			result = DC_FAIL_BANDWIDTH_VALIDATE;
2163 
2164 	return result;
2165 }
2166 
2167 static void patch_gamut_packet_checksum(
2168 		struct dc_info_packet *gamut_packet)
2169 {
2170 	/* For gamut we recalc checksum */
2171 	if (gamut_packet->valid) {
2172 		uint8_t chk_sum = 0;
2173 		uint8_t *ptr;
2174 		uint8_t i;
2175 
2176 		/*start of the Gamut data. */
2177 		ptr = &gamut_packet->sb[3];
2178 
2179 		for (i = 0; i <= gamut_packet->sb[1]; i++)
2180 			chk_sum += ptr[i];
2181 
2182 		gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
2183 	}
2184 }
2185 
2186 static void set_avi_info_frame(
2187 		struct dc_info_packet *info_packet,
2188 		struct pipe_ctx *pipe_ctx)
2189 {
2190 	struct dc_stream_state *stream = pipe_ctx->stream;
2191 	enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
2192 	uint32_t pixel_encoding = 0;
2193 	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
2194 	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
2195 	bool itc = false;
2196 	uint8_t itc_value = 0;
2197 	uint8_t cn0_cn1 = 0;
2198 	unsigned int cn0_cn1_value = 0;
2199 	uint8_t *check_sum = NULL;
2200 	uint8_t byte_index = 0;
2201 	union hdmi_info_packet hdmi_info;
2202 	union display_content_support support = {0};
2203 	unsigned int vic = pipe_ctx->stream->timing.vic;
2204 	enum dc_timing_3d_format format;
2205 
2206 	memset(&hdmi_info, 0, sizeof(union hdmi_info_packet));
2207 
2208 	color_space = pipe_ctx->stream->output_color_space;
2209 	if (color_space == COLOR_SPACE_UNKNOWN)
2210 		color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ?
2211 			COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709;
2212 
2213 	/* Initialize header */
2214 	hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
2215 	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
2216 	* not be used in HDMI 2.0 (Section 10.1) */
2217 	hdmi_info.bits.header.version = 2;
2218 	hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE;
2219 
2220 	/*
2221 	 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
2222 	 * according to HDMI 2.0 spec (Section 10.1)
2223 	 */
2224 
2225 	switch (stream->timing.pixel_encoding) {
2226 	case PIXEL_ENCODING_YCBCR422:
2227 		pixel_encoding = 1;
2228 		break;
2229 
2230 	case PIXEL_ENCODING_YCBCR444:
2231 		pixel_encoding = 2;
2232 		break;
2233 	case PIXEL_ENCODING_YCBCR420:
2234 		pixel_encoding = 3;
2235 		break;
2236 
2237 	case PIXEL_ENCODING_RGB:
2238 	default:
2239 		pixel_encoding = 0;
2240 	}
2241 
2242 	/* Y0_Y1_Y2 : The pixel encoding */
2243 	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
2244 	hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding;
2245 
2246 	/* A0 = 1 Active Format Information valid */
2247 	hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID;
2248 
2249 	/* B0, B1 = 3; Bar info data is valid */
2250 	hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID;
2251 
2252 	hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM;
2253 
2254 	/* S0, S1 : Underscan / Overscan */
2255 	/* TODO: un-hardcode scan type */
2256 	scan_type = SCANNING_TYPE_UNDERSCAN;
2257 	hdmi_info.bits.S0_S1 = scan_type;
2258 
2259 	/* C0, C1 : Colorimetry */
2260 	if (color_space == COLOR_SPACE_YCBCR709 ||
2261 			color_space == COLOR_SPACE_YCBCR709_LIMITED)
2262 		hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
2263 	else if (color_space == COLOR_SPACE_YCBCR601 ||
2264 			color_space == COLOR_SPACE_YCBCR601_LIMITED)
2265 		hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601;
2266 	else {
2267 		hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
2268 	}
2269 	if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
2270 			color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
2271 			color_space == COLOR_SPACE_2020_YCBCR) {
2272 		hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
2273 		hdmi_info.bits.C0_C1   = COLORIMETRY_EXTENDED;
2274 	} else if (color_space == COLOR_SPACE_ADOBERGB) {
2275 		hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
2276 		hdmi_info.bits.C0_C1   = COLORIMETRY_EXTENDED;
2277 	}
2278 
2279 	/* TODO: un-hardcode aspect ratio */
2280 	aspect = stream->timing.aspect_ratio;
2281 
2282 	switch (aspect) {
2283 	case ASPECT_RATIO_4_3:
2284 	case ASPECT_RATIO_16_9:
2285 		hdmi_info.bits.M0_M1 = aspect;
2286 		break;
2287 
2288 	case ASPECT_RATIO_NO_DATA:
2289 	case ASPECT_RATIO_64_27:
2290 	case ASPECT_RATIO_256_135:
2291 	default:
2292 		hdmi_info.bits.M0_M1 = 0;
2293 	}
2294 
2295 	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
2296 	hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
2297 
2298 	/* TODO: un-hardcode cn0_cn1 and itc */
2299 
2300 	cn0_cn1 = 0;
2301 	cn0_cn1_value = 0;
2302 
2303 	itc = true;
2304 	itc_value = 1;
2305 
2306 	support = stream->content_support;
2307 
2308 	if (itc) {
2309 		if (!support.bits.valid_content_type) {
2310 			cn0_cn1_value = 0;
2311 		} else {
2312 			if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) {
2313 				if (support.bits.graphics_content == 1) {
2314 					cn0_cn1_value = 0;
2315 				}
2316 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) {
2317 				if (support.bits.photo_content == 1) {
2318 					cn0_cn1_value = 1;
2319 				} else {
2320 					cn0_cn1_value = 0;
2321 					itc_value = 0;
2322 				}
2323 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) {
2324 				if (support.bits.cinema_content == 1) {
2325 					cn0_cn1_value = 2;
2326 				} else {
2327 					cn0_cn1_value = 0;
2328 					itc_value = 0;
2329 				}
2330 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) {
2331 				if (support.bits.game_content == 1) {
2332 					cn0_cn1_value = 3;
2333 				} else {
2334 					cn0_cn1_value = 0;
2335 					itc_value = 0;
2336 				}
2337 			}
2338 		}
2339 		hdmi_info.bits.CN0_CN1 = cn0_cn1_value;
2340 		hdmi_info.bits.ITC = itc_value;
2341 	}
2342 
2343 	if (stream->qs_bit == 1) {
2344 		if (color_space == COLOR_SPACE_SRGB ||
2345 			color_space == COLOR_SPACE_2020_RGB_FULLRANGE)
2346 			hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_FULL_RANGE;
2347 		else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
2348 					color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)
2349 			hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_LIMITED_RANGE;
2350 		else
2351 			hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_DEFAULT_RANGE;
2352 	} else
2353 		hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_DEFAULT_RANGE;
2354 
2355 	/* TODO : We should handle YCC quantization */
2356 	/* but we do not have matrix calculation */
2357 	if (stream->qy_bit == 1) {
2358 		if (color_space == COLOR_SPACE_SRGB ||
2359 			color_space == COLOR_SPACE_2020_RGB_FULLRANGE)
2360 			hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2361 		else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
2362 					color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)
2363 			hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2364 		else
2365 			hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2366 	} else
2367 		hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2368 
2369 	///VIC
2370 	format = stream->timing.timing_3d_format;
2371 	/*todo, add 3DStereo support*/
2372 	if (format != TIMING_3D_FORMAT_NONE) {
2373 		// Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled
2374 		switch (pipe_ctx->stream->timing.hdmi_vic) {
2375 		case 1:
2376 			vic = 95;
2377 			break;
2378 		case 2:
2379 			vic = 94;
2380 			break;
2381 		case 3:
2382 			vic = 93;
2383 			break;
2384 		case 4:
2385 			vic = 98;
2386 			break;
2387 		default:
2388 			break;
2389 		}
2390 	}
2391 	/* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/
2392 	hdmi_info.bits.VIC0_VIC7 = vic;
2393 	if (vic >= 128)
2394 		hdmi_info.bits.header.version = 3;
2395 	/* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1),
2396 	 * the Source shall use 20 AVI InfoFrame Version 4
2397 	 */
2398 	if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED &&
2399 			hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) {
2400 		hdmi_info.bits.header.version = 4;
2401 		hdmi_info.bits.header.length = 14;
2402 	}
2403 
2404 	/* pixel repetition
2405 	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
2406 	 * repetition start from 1 */
2407 	hdmi_info.bits.PR0_PR3 = 0;
2408 
2409 	/* Bar Info
2410 	 * barTop:    Line Number of End of Top Bar.
2411 	 * barBottom: Line Number of Start of Bottom Bar.
2412 	 * barLeft:   Pixel Number of End of Left Bar.
2413 	 * barRight:  Pixel Number of Start of Right Bar. */
2414 	hdmi_info.bits.bar_top = stream->timing.v_border_top;
2415 	hdmi_info.bits.bar_bottom = (stream->timing.v_total
2416 			- stream->timing.v_border_bottom + 1);
2417 	hdmi_info.bits.bar_left  = stream->timing.h_border_left;
2418 	hdmi_info.bits.bar_right = (stream->timing.h_total
2419 			- stream->timing.h_border_right + 1);
2420 
2421     /* Additional Colorimetry Extension
2422      * Used in conduction with C0-C1 and EC0-EC2
2423      * 0 = DCI-P3 RGB (D65)
2424      * 1 = DCI-P3 RGB (theater)
2425      */
2426 	hdmi_info.bits.ACE0_ACE3 = 0;
2427 
2428 	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
2429 	check_sum = &hdmi_info.packet_raw_data.sb[0];
2430 
2431 	*check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version;
2432 
2433 	for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++)
2434 		*check_sum += hdmi_info.packet_raw_data.sb[byte_index];
2435 
2436 	/* one byte complement */
2437 	*check_sum = (uint8_t) (0x100 - *check_sum);
2438 
2439 	/* Store in hw_path_mode */
2440 	info_packet->hb0 = hdmi_info.packet_raw_data.hb0;
2441 	info_packet->hb1 = hdmi_info.packet_raw_data.hb1;
2442 	info_packet->hb2 = hdmi_info.packet_raw_data.hb2;
2443 
2444 	for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++)
2445 		info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index];
2446 
2447 	info_packet->valid = true;
2448 }
2449 
2450 static void set_vendor_info_packet(
2451 		struct dc_info_packet *info_packet,
2452 		struct dc_stream_state *stream)
2453 {
2454 	/* SPD info packet for FreeSync */
2455 
2456 	/* Check if Freesync is supported. Return if false. If true,
2457 	 * set the corresponding bit in the info packet
2458 	 */
2459 	if (!stream->vsp_infopacket.valid)
2460 		return;
2461 
2462 	*info_packet = stream->vsp_infopacket;
2463 }
2464 
2465 static void set_spd_info_packet(
2466 		struct dc_info_packet *info_packet,
2467 		struct dc_stream_state *stream)
2468 {
2469 	/* SPD info packet for FreeSync */
2470 
2471 	/* Check if Freesync is supported. Return if false. If true,
2472 	 * set the corresponding bit in the info packet
2473 	 */
2474 	if (!stream->vrr_infopacket.valid)
2475 		return;
2476 
2477 	*info_packet = stream->vrr_infopacket;
2478 }
2479 
2480 static void set_hdr_static_info_packet(
2481 		struct dc_info_packet *info_packet,
2482 		struct dc_stream_state *stream)
2483 {
2484 	/* HDR Static Metadata info packet for HDR10 */
2485 
2486 	if (!stream->hdr_static_metadata.valid ||
2487 			stream->use_dynamic_meta)
2488 		return;
2489 
2490 	*info_packet = stream->hdr_static_metadata;
2491 }
2492 
2493 static void set_vsc_info_packet(
2494 		struct dc_info_packet *info_packet,
2495 		struct dc_stream_state *stream)
2496 {
2497 	if (!stream->vsc_infopacket.valid)
2498 		return;
2499 
2500 	*info_packet = stream->vsc_infopacket;
2501 }
2502 
2503 void dc_resource_state_destruct(struct dc_state *context)
2504 {
2505 	int i, j;
2506 
2507 	for (i = 0; i < context->stream_count; i++) {
2508 		for (j = 0; j < context->stream_status[i].plane_count; j++)
2509 			dc_plane_state_release(
2510 				context->stream_status[i].plane_states[j]);
2511 
2512 		context->stream_status[i].plane_count = 0;
2513 		dc_stream_release(context->streams[i]);
2514 		context->streams[i] = NULL;
2515 	}
2516 	context->stream_count = 0;
2517 }
2518 
2519 void dc_resource_state_copy_construct(
2520 		const struct dc_state *src_ctx,
2521 		struct dc_state *dst_ctx)
2522 {
2523 	int i, j;
2524 	struct kref refcount = dst_ctx->refcount;
2525 
2526 	*dst_ctx = *src_ctx;
2527 
2528 	for (i = 0; i < MAX_PIPES; i++) {
2529 		struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
2530 
2531 		if (cur_pipe->top_pipe)
2532 			cur_pipe->top_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
2533 
2534 		if (cur_pipe->bottom_pipe)
2535 			cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
2536 
2537 		if (cur_pipe->next_odm_pipe)
2538 			cur_pipe->next_odm_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
2539 
2540 		if (cur_pipe->prev_odm_pipe)
2541 			cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
2542 	}
2543 
2544 	for (i = 0; i < dst_ctx->stream_count; i++) {
2545 		dc_stream_retain(dst_ctx->streams[i]);
2546 		for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++)
2547 			dc_plane_state_retain(
2548 				dst_ctx->stream_status[i].plane_states[j]);
2549 	}
2550 
2551 	/* context refcount should not be overridden */
2552 	dst_ctx->refcount = refcount;
2553 
2554 }
2555 
2556 struct clock_source *dc_resource_find_first_free_pll(
2557 		struct resource_context *res_ctx,
2558 		const struct resource_pool *pool)
2559 {
2560 	int i;
2561 
2562 	for (i = 0; i < pool->clk_src_count; ++i) {
2563 		if (res_ctx->clock_source_ref_count[i] == 0)
2564 			return pool->clock_sources[i];
2565 	}
2566 
2567 	return NULL;
2568 }
2569 
2570 void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
2571 {
2572 	enum signal_type signal = SIGNAL_TYPE_NONE;
2573 	struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame;
2574 
2575 	/* default all packets to invalid */
2576 	info->avi.valid = false;
2577 	info->gamut.valid = false;
2578 	info->vendor.valid = false;
2579 	info->spd.valid = false;
2580 	info->hdrsmd.valid = false;
2581 	info->vsc.valid = false;
2582 
2583 	signal = pipe_ctx->stream->signal;
2584 
2585 	/* HDMi and DP have different info packets*/
2586 	if (dc_is_hdmi_signal(signal)) {
2587 		set_avi_info_frame(&info->avi, pipe_ctx);
2588 
2589 		set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
2590 
2591 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
2592 
2593 		set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
2594 
2595 	} else if (dc_is_dp_signal(signal)) {
2596 		set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
2597 
2598 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
2599 
2600 		set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
2601 	}
2602 
2603 	patch_gamut_packet_checksum(&info->gamut);
2604 }
2605 
2606 enum dc_status resource_map_clock_resources(
2607 		const struct dc  *dc,
2608 		struct dc_state *context,
2609 		struct dc_stream_state *stream)
2610 {
2611 	/* acquire new resources */
2612 	const struct resource_pool *pool = dc->res_pool;
2613 	struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(
2614 				&context->res_ctx, stream);
2615 
2616 	if (!pipe_ctx)
2617 		return DC_ERROR_UNEXPECTED;
2618 
2619 	if (dc_is_dp_signal(pipe_ctx->stream->signal)
2620 		|| pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
2621 		pipe_ctx->clock_source = pool->dp_clock_source;
2622 	else {
2623 		pipe_ctx->clock_source = NULL;
2624 
2625 		if (!dc->config.disable_disp_pll_sharing)
2626 			pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing(
2627 				&context->res_ctx,
2628 				pipe_ctx);
2629 
2630 		if (pipe_ctx->clock_source == NULL)
2631 			pipe_ctx->clock_source =
2632 				dc_resource_find_first_free_pll(
2633 					&context->res_ctx,
2634 					pool);
2635 	}
2636 
2637 	if (pipe_ctx->clock_source == NULL)
2638 		return DC_NO_CLOCK_SOURCE_RESOURCE;
2639 
2640 	resource_reference_clock_source(
2641 		&context->res_ctx, pool,
2642 		pipe_ctx->clock_source);
2643 
2644 	return DC_OK;
2645 }
2646 
2647 /*
2648  * Note: We need to disable output if clock sources change,
2649  * since bios does optimization and doesn't apply if changing
2650  * PHY when not already disabled.
2651  */
2652 bool pipe_need_reprogram(
2653 		struct pipe_ctx *pipe_ctx_old,
2654 		struct pipe_ctx *pipe_ctx)
2655 {
2656 	if (!pipe_ctx_old->stream)
2657 		return false;
2658 
2659 	if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
2660 		return true;
2661 
2662 	if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
2663 		return true;
2664 
2665 	if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio)
2666 		return true;
2667 
2668 	if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
2669 			&& pipe_ctx_old->stream != pipe_ctx->stream)
2670 		return true;
2671 
2672 	if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc)
2673 		return true;
2674 
2675 	if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
2676 		return true;
2677 
2678 	if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off)
2679 		return true;
2680 
2681 	if (false == pipe_ctx_old->stream->link->link_state_valid &&
2682 		false == pipe_ctx_old->stream->dpms_off)
2683 		return true;
2684 
2685 	if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc)
2686 		return true;
2687 
2688 	/* DIG link encoder resource assignment for stream changed. */
2689 	if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc)
2690 		return true;
2691 
2692 	return false;
2693 }
2694 
2695 void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
2696 		struct bit_depth_reduction_params *fmt_bit_depth)
2697 {
2698 	enum dc_dither_option option = stream->dither_option;
2699 	enum dc_pixel_encoding pixel_encoding =
2700 			stream->timing.pixel_encoding;
2701 
2702 	memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
2703 
2704 	if (option == DITHER_OPTION_DEFAULT) {
2705 		switch (stream->timing.display_color_depth) {
2706 		case COLOR_DEPTH_666:
2707 			option = DITHER_OPTION_SPATIAL6;
2708 			break;
2709 		case COLOR_DEPTH_888:
2710 			option = DITHER_OPTION_SPATIAL8;
2711 			break;
2712 		case COLOR_DEPTH_101010:
2713 			option = DITHER_OPTION_SPATIAL10;
2714 			break;
2715 		default:
2716 			option = DITHER_OPTION_DISABLE;
2717 		}
2718 	}
2719 
2720 	if (option == DITHER_OPTION_DISABLE)
2721 		return;
2722 
2723 	if (option == DITHER_OPTION_TRUN6) {
2724 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2725 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 0;
2726 	} else if (option == DITHER_OPTION_TRUN8 ||
2727 			option == DITHER_OPTION_TRUN8_SPATIAL6 ||
2728 			option == DITHER_OPTION_TRUN8_FM6) {
2729 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2730 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 1;
2731 	} else if (option == DITHER_OPTION_TRUN10        ||
2732 			option == DITHER_OPTION_TRUN10_SPATIAL6   ||
2733 			option == DITHER_OPTION_TRUN10_SPATIAL8   ||
2734 			option == DITHER_OPTION_TRUN10_FM8     ||
2735 			option == DITHER_OPTION_TRUN10_FM6     ||
2736 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2737 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2738 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2739 	}
2740 
2741 	/* special case - Formatter can only reduce by 4 bits at most.
2742 	 * When reducing from 12 to 6 bits,
2743 	 * HW recommends we use trunc with round mode
2744 	 * (if we did nothing, trunc to 10 bits would be used)
2745 	 * note that any 12->10 bit reduction is ignored prior to DCE8,
2746 	 * as the input was 10 bits.
2747 	 */
2748 	if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM ||
2749 			option == DITHER_OPTION_SPATIAL6 ||
2750 			option == DITHER_OPTION_FM6) {
2751 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2752 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2753 		fmt_bit_depth->flags.TRUNCATE_MODE = 1;
2754 	}
2755 
2756 	/* spatial dither
2757 	 * note that spatial modes 1-3 are never used
2758 	 */
2759 	if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM            ||
2760 			option == DITHER_OPTION_SPATIAL6 ||
2761 			option == DITHER_OPTION_TRUN10_SPATIAL6      ||
2762 			option == DITHER_OPTION_TRUN8_SPATIAL6) {
2763 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2764 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
2765 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2766 		fmt_bit_depth->flags.RGB_RANDOM =
2767 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2768 	} else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM            ||
2769 			option == DITHER_OPTION_SPATIAL8 ||
2770 			option == DITHER_OPTION_SPATIAL8_FM6        ||
2771 			option == DITHER_OPTION_TRUN10_SPATIAL8      ||
2772 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2773 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2774 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
2775 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2776 		fmt_bit_depth->flags.RGB_RANDOM =
2777 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2778 	} else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM ||
2779 			option == DITHER_OPTION_SPATIAL10 ||
2780 			option == DITHER_OPTION_SPATIAL10_FM8 ||
2781 			option == DITHER_OPTION_SPATIAL10_FM6) {
2782 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2783 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
2784 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2785 		fmt_bit_depth->flags.RGB_RANDOM =
2786 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2787 	}
2788 
2789 	if (option == DITHER_OPTION_SPATIAL6 ||
2790 			option == DITHER_OPTION_SPATIAL8 ||
2791 			option == DITHER_OPTION_SPATIAL10) {
2792 		fmt_bit_depth->flags.FRAME_RANDOM = 0;
2793 	} else {
2794 		fmt_bit_depth->flags.FRAME_RANDOM = 1;
2795 	}
2796 
2797 	//////////////////////
2798 	//// temporal dither
2799 	//////////////////////
2800 	if (option == DITHER_OPTION_FM6           ||
2801 			option == DITHER_OPTION_SPATIAL8_FM6     ||
2802 			option == DITHER_OPTION_SPATIAL10_FM6     ||
2803 			option == DITHER_OPTION_TRUN10_FM6     ||
2804 			option == DITHER_OPTION_TRUN8_FM6      ||
2805 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2806 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2807 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0;
2808 	} else if (option == DITHER_OPTION_FM8        ||
2809 			option == DITHER_OPTION_SPATIAL10_FM8  ||
2810 			option == DITHER_OPTION_TRUN10_FM8) {
2811 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2812 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1;
2813 	} else if (option == DITHER_OPTION_FM10) {
2814 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2815 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2;
2816 	}
2817 
2818 	fmt_bit_depth->pixel_encoding = pixel_encoding;
2819 }
2820 
2821 enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
2822 {
2823 	struct dc_link *link = stream->link;
2824 	struct timing_generator *tg = dc->res_pool->timing_generators[0];
2825 	enum dc_status res = DC_OK;
2826 
2827 	calculate_phy_pix_clks(stream);
2828 
2829 	if (!tg->funcs->validate_timing(tg, &stream->timing))
2830 		res = DC_FAIL_CONTROLLER_VALIDATE;
2831 
2832 	if (res == DC_OK) {
2833 		if (!link->link_enc->funcs->validate_output_with_stream(
2834 						link->link_enc, stream))
2835 			res = DC_FAIL_ENC_VALIDATE;
2836 	}
2837 
2838 	/* TODO: validate audio ASIC caps, encoder */
2839 
2840 	if (res == DC_OK)
2841 		res = dc_link_validate_mode_timing(stream,
2842 		      link,
2843 		      &stream->timing);
2844 
2845 	return res;
2846 }
2847 
2848 enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state)
2849 {
2850 	enum dc_status res = DC_OK;
2851 
2852 	/* TODO For now validates pixel format only */
2853 	if (dc->res_pool->funcs->validate_plane)
2854 		return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps);
2855 
2856 	return res;
2857 }
2858 
2859 unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
2860 {
2861 	switch (format) {
2862 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
2863 		return 8;
2864 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
2865 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
2866 		return 12;
2867 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
2868 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
2869 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
2870 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
2871 		return 16;
2872 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
2873 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
2874 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
2875 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
2876 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
2877 #if defined(CONFIG_DRM_AMD_DC_DCN)
2878 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
2879 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
2880 #endif
2881 		return 32;
2882 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
2883 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
2884 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
2885 		return 64;
2886 	default:
2887 		ASSERT_CRITICAL(false);
2888 		return -1;
2889 	}
2890 }
2891 static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
2892 {
2893 	if (modes) {
2894 		if (modes->sample_rates.rate.RATE_192)
2895 			return 192000;
2896 		if (modes->sample_rates.rate.RATE_176_4)
2897 			return 176400;
2898 		if (modes->sample_rates.rate.RATE_96)
2899 			return 96000;
2900 		if (modes->sample_rates.rate.RATE_88_2)
2901 			return 88200;
2902 		if (modes->sample_rates.rate.RATE_48)
2903 			return 48000;
2904 		if (modes->sample_rates.rate.RATE_44_1)
2905 			return 44100;
2906 		if (modes->sample_rates.rate.RATE_32)
2907 			return 32000;
2908 	}
2909 	/*original logic when no audio info*/
2910 	return 441000;
2911 }
2912 
2913 void get_audio_check(struct audio_info *aud_modes,
2914 	struct audio_check *audio_chk)
2915 {
2916 	unsigned int i;
2917 	unsigned int max_sample_rate = 0;
2918 
2919 	if (aud_modes) {
2920 		audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/
2921 
2922 		audio_chk->max_audiosample_rate = 0;
2923 		for (i = 0; i < aud_modes->mode_count; i++) {
2924 			max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]);
2925 			if (audio_chk->max_audiosample_rate < max_sample_rate)
2926 				audio_chk->max_audiosample_rate = max_sample_rate;
2927 			/*dts takes the same as type 2: AP = 0.25*/
2928 		}
2929 		/*check which one take more bandwidth*/
2930 		if (audio_chk->max_audiosample_rate > 192000)
2931 			audio_chk->audio_packet_type = 0x9;/*AP =1*/
2932 		audio_chk->acat = 0;/*not support*/
2933 	}
2934 }
2935 
2936