xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/core/amdgpu_dc_resource.c (revision b0cb4d44dd18a4c2aa4f36aa96fd7726e1cf9bbb)
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 
resource_parse_asic_id(struct hw_asic_id asic_id)63 enum 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 
dc_create_resource_pool(struct dc * dc,const struct dc_init_data * init_data,enum dce_version dc_version)123 struct 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 
dc_destroy_resource_pool(struct dc * dc)202 void 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 
update_num_audio(const struct resource_straps * straps,unsigned int * num_audio,struct audio_support * aud_support)212 static 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 
resource_construct(unsigned int num_virtual_links,struct dc * dc,struct resource_pool * pool,const struct resource_create_funcs * create_funcs)239 bool 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 }
find_matching_clock_source(const struct resource_pool * pool,struct clock_source * clock_source)309 static 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 
resource_unreference_clock_source(struct resource_context * res_ctx,const struct resource_pool * pool,struct clock_source * clock_source)323 void 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 
resource_reference_clock_source(struct resource_context * res_ctx,const struct resource_pool * pool,struct clock_source * clock_source)337 void 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 
resource_get_clock_source_reference(struct resource_context * res_ctx,const struct resource_pool * pool,struct clock_source * clock_source)351 int 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 
resource_are_streams_timing_synchronizable(struct dc_stream_state * stream1,struct dc_stream_state * stream2)367 bool 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 }
is_dp_and_hdmi_sharable(struct dc_stream_state * stream1,struct dc_stream_state * stream2)405 static 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 
is_sharable_clk_src(const struct pipe_ctx * pipe_with_clk_src,const struct pipe_ctx * pipe)420 static 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 
resource_find_used_clk_src_for_sharing(struct resource_context * res_ctx,struct pipe_ctx * pipe_ctx)451 struct 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 
convert_pixel_format_to_dalsurface(enum surface_pixel_format surface_pixel_format)465 static 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 
get_vp_scan_direction(enum dc_rotation_angle rotation,bool horizontal_mirror,bool * orthogonal_rotation,bool * flip_vert_scan_dir,bool * flip_horz_scan_dir)515 static 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 
calculate_viewport(struct pipe_ctx * pipe_ctx)540 static 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 
calculate_recout(struct pipe_ctx * pipe_ctx)648 static 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 
calculate_scaling_ratios(struct pipe_ctx * pipe_ctx)706 static 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 
adjust_vp_and_init_for_seamless_clip(bool flip_scan_dir,int recout_skip,int src_size,int taps,struct fixed31_32 ratio,struct fixed31_32 * init,int * vp_offset,int * vp_size)756 static 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 
calculate_inits_and_adj_vp(struct pipe_ctx * pipe_ctx)836 static 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  */
shift_border_left_to_dst(struct pipe_ctx * pipe_ctx)969 int 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 
restore_border_left_from_dst(struct pipe_ctx * pipe_ctx,int store_h_border_left)980 void 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 
resource_build_scaling_params(struct pipe_ctx * pipe_ctx)987 bool 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 
resource_build_scaling_params_for_context(const struct dc * dc,struct dc_state * context)1082 enum 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 
find_idle_secondary_pipe(struct resource_context * res_ctx,const struct resource_pool * pool,const struct pipe_ctx * primary_pipe)1098 struct 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 
resource_get_head_pipe_for_stream(struct resource_context * res_ctx,struct dc_stream_state * stream)1158 struct 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 
resource_get_tail_pipe(struct resource_context * res_ctx,struct pipe_ctx * head_pipe)1173 static 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  */
acquire_free_pipe_for_head(struct dc_state * context,const struct resource_pool * pool,struct pipe_ctx * head_pipe)1193 static 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)
acquire_first_split_pipe(struct resource_context * res_ctx,const struct resource_pool * pool,struct dc_stream_state * stream)1224 static 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 
dc_add_plane_to_context(const struct dc * dc,struct dc_stream_state * stream,struct dc_plane_state * plane_state,struct dc_state * context)1260 bool 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 
dc_remove_plane_from_context(const struct dc * dc,struct dc_stream_state * stream,struct dc_plane_state * plane_state,struct dc_state * context)1338 bool 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 
dc_rem_all_planes_for_stream(const struct dc * dc,struct dc_stream_state * stream,struct dc_state * context)1410 bool 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 
add_all_planes_for_stream(const struct dc * dc,struct dc_stream_state * stream,const struct dc_validation_set set[],int set_count,struct dc_state * context)1442 static 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 
dc_add_all_planes_for_stream(const struct dc * dc,struct dc_stream_state * stream,struct dc_plane_state * const * plane_states,int plane_count,struct dc_state * context)1467 bool 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 
is_hdr_static_meta_changed(struct dc_stream_state * cur_stream,struct dc_stream_state * new_stream)1487 static 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 
is_vsc_info_packet_changed(struct dc_stream_state * cur_stream,struct dc_stream_state * new_stream)1501 static 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 
is_timing_changed(struct dc_stream_state * cur_stream,struct dc_stream_state * new_stream)1515 static 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 
are_stream_backends_same(struct dc_stream_state * stream_a,struct dc_stream_state * stream_b)1537 static 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  */
dc_is_stream_unchanged(struct dc_stream_state * old_stream,struct dc_stream_state * stream)1569 bool 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  */
dc_is_stream_scaling_unchanged(struct dc_stream_state * old_stream,struct dc_stream_state * stream)1585 bool 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 
update_stream_engine_usage(struct resource_context * res_ctx,const struct resource_pool * pool,struct stream_encoder * stream_enc,bool acquired)1607 static 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 */
update_audio_usage(struct resource_context * res_ctx,const struct resource_pool * pool,struct audio * audio,bool acquired)1622 void 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 
acquire_first_free_pipe(struct resource_context * res_ctx,const struct resource_pool * pool,struct dc_stream_state * stream)1635 static 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 
find_first_free_audio(struct resource_context * res_ctx,const struct resource_pool * pool,enum engine_id id,enum dce_version dc_version)1665 static 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 
resource_is_stream_unchanged(struct dc_state * old_context,struct dc_stream_state * stream)1697 bool 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  */
dc_add_stream_to_ctx(struct dc * dc,struct dc_state * new_ctx,struct dc_stream_state * stream)1715 enum 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  */
dc_remove_stream_from_ctx(struct dc * dc,struct dc_state * new_ctx,struct dc_stream_state * stream)1742 enum 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 
find_pll_sharable_stream(struct dc_stream_state * stream_needs_pll,struct dc_state * context)1816 static 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 
get_norm_pix_clk(const struct dc_crtc_timing * timing)1838 static 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 
calculate_phy_pix_clks(struct dc_stream_state * stream)1868 static 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 
acquire_resource_from_hw_enabled_state(struct resource_context * res_ctx,const struct resource_pool * pool,struct dc_stream_state * stream)1882 static 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 
resource_map_pool_resources(const struct dc * dc,struct dc_state * context,struct dc_stream_state * stream)1954 enum 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  */
dc_resource_state_copy_construct_current(const struct dc * dc,struct dc_state * dst_ctx)2059 void 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 
dc_resource_state_construct(const struct dc * dc,struct dc_state * dst_ctx)2067 void 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 
dc_resource_is_dsc_encoding_supported(const struct dc * dc)2075 bool 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  */
dc_validate_global_state(struct dc * dc,struct dc_state * new_ctx,bool fast_validate)2090 enum 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 
patch_gamut_packet_checksum(struct dc_info_packet * gamut_packet)2154 static 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 
set_avi_info_frame(struct dc_info_packet * info_packet,struct pipe_ctx * pipe_ctx)2173 static 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 
set_vendor_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)2432 static 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 
set_spd_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)2447 static 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 
set_hdr_static_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)2462 static 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 
set_vsc_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)2475 static 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 
dc_resource_state_destruct(struct dc_state * context)2485 void 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 
dc_resource_state_copy_construct(const struct dc_state * src_ctx,struct dc_state * dst_ctx)2500 void 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 
dc_resource_find_first_free_pll(struct resource_context * res_ctx,const struct resource_pool * pool)2537 struct 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 
resource_build_info_frame(struct pipe_ctx * pipe_ctx)2551 void 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 
resource_map_clock_resources(const struct dc * dc,struct dc_state * context,struct dc_stream_state * stream)2587 enum 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  */
pipe_need_reprogram(struct pipe_ctx * pipe_ctx_old,struct pipe_ctx * pipe_ctx)2633 bool 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 
resource_build_bit_depth_reduction_params(struct dc_stream_state * stream,struct bit_depth_reduction_params * fmt_bit_depth)2675 void 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 
dc_validate_stream(struct dc * dc,struct dc_stream_state * stream)2801 enum 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 
dc_validate_plane(struct dc * dc,const struct dc_plane_state * plane_state)2828 enum 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 
resource_pixel_format_to_bpp(enum surface_pixel_format format)2839 unsigned 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 }
get_max_audio_sample_rate(struct audio_mode * modes)2867 static 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 
get_audio_check(struct audio_info * aud_modes,struct audio_check * audio_chk)2889 void 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