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