Home | History | Annotate | Line # | Download | only in core
      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 
     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 
    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 
    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 
    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 
    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 }
    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 
    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 
    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 
    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 
    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 }
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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 
    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 
    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 
   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 
   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 
   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 
   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  */
   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)
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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  */
   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  */
   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 
   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 */
   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 
   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 
   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 
   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  */
   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  */
   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 
   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 
   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 
   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 
   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 
   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  */
   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 
   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 
   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  */
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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  */
   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 
   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 
   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 
   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 
   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 }
   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 
   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