14562236bSHarry Wentland /*
24562236bSHarry Wentland * Copyright 2012-15 Advanced Micro Devices, Inc.
34562236bSHarry Wentland  *
44562236bSHarry Wentland  * Permission is hereby granted, free of charge, to any person obtaining a
54562236bSHarry Wentland  * copy of this software and associated documentation files (the "Software"),
64562236bSHarry Wentland  * to deal in the Software without restriction, including without limitation
74562236bSHarry Wentland  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84562236bSHarry Wentland  * and/or sell copies of the Software, and to permit persons to whom the
94562236bSHarry Wentland  * Software is furnished to do so, subject to the following conditions:
104562236bSHarry Wentland  *
114562236bSHarry Wentland  * The above copyright notice and this permission notice shall be included in
124562236bSHarry Wentland  * all copies or substantial portions of the Software.
134562236bSHarry Wentland  *
144562236bSHarry Wentland  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154562236bSHarry Wentland  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
164562236bSHarry Wentland  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
174562236bSHarry Wentland  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
184562236bSHarry Wentland  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
194562236bSHarry Wentland  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
204562236bSHarry Wentland  * OTHER DEALINGS IN THE SOFTWARE.
214562236bSHarry Wentland  *
224562236bSHarry Wentland  * Authors: AMD
234562236bSHarry Wentland  *
244562236bSHarry Wentland  */
254562236bSHarry Wentland #include "dm_services.h"
264562236bSHarry Wentland 
274562236bSHarry Wentland #include "resource.h"
284562236bSHarry Wentland #include "include/irq_service_interface.h"
294562236bSHarry Wentland #include "link_encoder.h"
304562236bSHarry Wentland #include "stream_encoder.h"
314562236bSHarry Wentland #include "opp.h"
324562236bSHarry Wentland #include "timing_generator.h"
334562236bSHarry Wentland #include "transform.h"
345ac3d3c9SCharlene Liu #include "core_types.h"
354562236bSHarry Wentland #include "set_mode_types.h"
364562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h"
374562236bSHarry Wentland 
384562236bSHarry Wentland #include "dce80/dce80_resource.h"
394562236bSHarry Wentland #include "dce100/dce100_resource.h"
404562236bSHarry Wentland #include "dce110/dce110_resource.h"
414562236bSHarry Wentland #include "dce112/dce112_resource.h"
422c8ad2d5SAlex Deucher #include "dce120/dce120_resource.h"
434562236bSHarry Wentland 
444562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
454562236bSHarry Wentland {
464562236bSHarry Wentland 	enum dce_version dc_version = DCE_VERSION_UNKNOWN;
474562236bSHarry Wentland 	switch (asic_id.chip_family) {
484562236bSHarry Wentland 
494562236bSHarry Wentland 	case FAMILY_CI:
504562236bSHarry Wentland 	case FAMILY_KV:
514562236bSHarry Wentland 		dc_version = DCE_VERSION_8_0;
524562236bSHarry Wentland 		break;
534562236bSHarry Wentland 	case FAMILY_CZ:
544562236bSHarry Wentland 		dc_version = DCE_VERSION_11_0;
554562236bSHarry Wentland 		break;
564562236bSHarry Wentland 
574562236bSHarry Wentland 	case FAMILY_VI:
584562236bSHarry Wentland 		if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
594562236bSHarry Wentland 				ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
604562236bSHarry Wentland 			dc_version = DCE_VERSION_10_0;
614562236bSHarry Wentland 			break;
624562236bSHarry Wentland 		}
634562236bSHarry Wentland 		if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
64b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
65b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
664562236bSHarry Wentland 			dc_version = DCE_VERSION_11_2;
674562236bSHarry Wentland 		}
684562236bSHarry Wentland 		break;
692c8ad2d5SAlex Deucher 	case FAMILY_AI:
702c8ad2d5SAlex Deucher 		dc_version = DCE_VERSION_12_0;
712c8ad2d5SAlex Deucher 		break;
724562236bSHarry Wentland 	default:
734562236bSHarry Wentland 		dc_version = DCE_VERSION_UNKNOWN;
744562236bSHarry Wentland 		break;
754562236bSHarry Wentland 	}
764562236bSHarry Wentland 	return dc_version;
774562236bSHarry Wentland }
784562236bSHarry Wentland 
794562236bSHarry Wentland struct resource_pool *dc_create_resource_pool(
804562236bSHarry Wentland 				struct core_dc *dc,
814562236bSHarry Wentland 				int num_virtual_links,
824562236bSHarry Wentland 				enum dce_version dc_version,
834562236bSHarry Wentland 				struct hw_asic_id asic_id)
844562236bSHarry Wentland {
855ac3d3c9SCharlene Liu 	struct resource_pool *res_pool = NULL;
864562236bSHarry Wentland 
874562236bSHarry Wentland 	switch (dc_version) {
884562236bSHarry Wentland 	case DCE_VERSION_8_0:
895ac3d3c9SCharlene Liu 		res_pool = dce80_create_resource_pool(
904562236bSHarry Wentland 			num_virtual_links, dc);
915ac3d3c9SCharlene Liu 		break;
924562236bSHarry Wentland 	case DCE_VERSION_10_0:
935ac3d3c9SCharlene Liu 		res_pool = dce100_create_resource_pool(
944562236bSHarry Wentland 				num_virtual_links, dc);
955ac3d3c9SCharlene Liu 		break;
964562236bSHarry Wentland 	case DCE_VERSION_11_0:
975ac3d3c9SCharlene Liu 		res_pool = dce110_create_resource_pool(
984562236bSHarry Wentland 			num_virtual_links, dc, asic_id);
995ac3d3c9SCharlene Liu 		break;
1004562236bSHarry Wentland 	case DCE_VERSION_11_2:
1015ac3d3c9SCharlene Liu 		res_pool = dce112_create_resource_pool(
1024562236bSHarry Wentland 			num_virtual_links, dc);
1035ac3d3c9SCharlene Liu 		break;
1042c8ad2d5SAlex Deucher 	case DCE_VERSION_12_0:
1052c8ad2d5SAlex Deucher 		res_pool = dce120_create_resource_pool(
1062c8ad2d5SAlex Deucher 			num_virtual_links, dc);
1072c8ad2d5SAlex Deucher 		break;
1084562236bSHarry Wentland 	default:
1094562236bSHarry Wentland 		break;
1104562236bSHarry Wentland 	}
1115ac3d3c9SCharlene Liu 	if (res_pool != NULL) {
1125ac3d3c9SCharlene Liu 		struct firmware_info fw_info = { { 0 } };
1134562236bSHarry Wentland 
1145ac3d3c9SCharlene Liu 		if (dc->ctx->dc_bios->funcs->get_firmware_info(
1155ac3d3c9SCharlene Liu 				dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) {
1165ac3d3c9SCharlene Liu 				res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency;
1175ac3d3c9SCharlene Liu 			} else
1185ac3d3c9SCharlene Liu 				ASSERT_CRITICAL(false);
1195ac3d3c9SCharlene Liu 	}
1205ac3d3c9SCharlene Liu 
1215ac3d3c9SCharlene Liu 	return res_pool;
1224562236bSHarry Wentland }
1234562236bSHarry Wentland 
1244562236bSHarry Wentland void dc_destroy_resource_pool(struct core_dc *dc)
1254562236bSHarry Wentland {
1264562236bSHarry Wentland 	if (dc) {
1274562236bSHarry Wentland 		if (dc->res_pool)
1284562236bSHarry Wentland 			dc->res_pool->funcs->destroy(&dc->res_pool);
1294562236bSHarry Wentland 
1304562236bSHarry Wentland 		if (dc->hwseq)
1314562236bSHarry Wentland 			dm_free(dc->hwseq);
1324562236bSHarry Wentland 	}
1334562236bSHarry Wentland }
1344562236bSHarry Wentland 
1354562236bSHarry Wentland static void update_num_audio(
1364562236bSHarry Wentland 	const struct resource_straps *straps,
1374562236bSHarry Wentland 	unsigned int *num_audio,
1384562236bSHarry Wentland 	struct audio_support *aud_support)
1394562236bSHarry Wentland {
1404562236bSHarry Wentland 	if (straps->hdmi_disable == 0) {
1414562236bSHarry Wentland 		aud_support->hdmi_audio_native = true;
1424562236bSHarry Wentland 		aud_support->hdmi_audio_on_dongle = true;
1434562236bSHarry Wentland 		aud_support->dp_audio = true;
1444562236bSHarry Wentland 	} else {
1454562236bSHarry Wentland 		if (straps->dc_pinstraps_audio & 0x2) {
1464562236bSHarry Wentland 			aud_support->hdmi_audio_on_dongle = true;
1474562236bSHarry Wentland 			aud_support->dp_audio = true;
1484562236bSHarry Wentland 		} else {
1494562236bSHarry Wentland 			aud_support->dp_audio = true;
1504562236bSHarry Wentland 		}
1514562236bSHarry Wentland 	}
1524562236bSHarry Wentland 
1534562236bSHarry Wentland 	switch (straps->audio_stream_number) {
1544562236bSHarry Wentland 	case 0: /* multi streams supported */
1554562236bSHarry Wentland 		break;
1564562236bSHarry Wentland 	case 1: /* multi streams not supported */
1574562236bSHarry Wentland 		*num_audio = 1;
1584562236bSHarry Wentland 		break;
1594562236bSHarry Wentland 	default:
1604562236bSHarry Wentland 		DC_ERR("DC: unexpected audio fuse!\n");
16117a96033SJulia Lawall 	}
1624562236bSHarry Wentland }
1634562236bSHarry Wentland 
1644562236bSHarry Wentland bool resource_construct(
1654562236bSHarry Wentland 	unsigned int num_virtual_links,
1664562236bSHarry Wentland 	struct core_dc *dc,
1674562236bSHarry Wentland 	struct resource_pool *pool,
1684562236bSHarry Wentland 	const struct resource_create_funcs *create_funcs)
1694562236bSHarry Wentland {
1704562236bSHarry Wentland 	struct dc_context *ctx = dc->ctx;
1714562236bSHarry Wentland 	const struct resource_caps *caps = pool->res_cap;
1724562236bSHarry Wentland 	int i;
1734562236bSHarry Wentland 	unsigned int num_audio = caps->num_audio;
1744562236bSHarry Wentland 	struct resource_straps straps = {0};
1754562236bSHarry Wentland 
1764562236bSHarry Wentland 	if (create_funcs->read_dce_straps)
1774562236bSHarry Wentland 		create_funcs->read_dce_straps(dc->ctx, &straps);
1784562236bSHarry Wentland 
1794562236bSHarry Wentland 	pool->audio_count = 0;
1804562236bSHarry Wentland 	if (create_funcs->create_audio) {
1814562236bSHarry Wentland 		/* find the total number of streams available via the
1824562236bSHarry Wentland 		 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
1834562236bSHarry Wentland 		 * registers (one for each pin) starting from pin 1
1844562236bSHarry Wentland 		 * up to the max number of audio pins.
1854562236bSHarry Wentland 		 * We stop on the first pin where
1864562236bSHarry Wentland 		 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
1874562236bSHarry Wentland 		 */
1884562236bSHarry Wentland 		update_num_audio(&straps, &num_audio, &pool->audio_support);
1894562236bSHarry Wentland 		for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
1904562236bSHarry Wentland 			struct audio *aud = create_funcs->create_audio(ctx, i);
1914562236bSHarry Wentland 
1924562236bSHarry Wentland 			if (aud == NULL) {
1934562236bSHarry Wentland 				DC_ERR("DC: failed to create audio!\n");
1944562236bSHarry Wentland 				return false;
1954562236bSHarry Wentland 			}
1964562236bSHarry Wentland 
1974562236bSHarry Wentland 			if (!aud->funcs->endpoint_valid(aud)) {
1984562236bSHarry Wentland 				aud->funcs->destroy(&aud);
1994562236bSHarry Wentland 				break;
2004562236bSHarry Wentland 			}
2014562236bSHarry Wentland 
2024562236bSHarry Wentland 			pool->audios[i] = aud;
2034562236bSHarry Wentland 			pool->audio_count++;
2044562236bSHarry Wentland 		}
2054562236bSHarry Wentland 	}
2064562236bSHarry Wentland 
2074562236bSHarry Wentland 	pool->stream_enc_count = 0;
2084562236bSHarry Wentland 	if (create_funcs->create_stream_encoder) {
2094562236bSHarry Wentland 		for (i = 0; i < caps->num_stream_encoder; i++) {
2104562236bSHarry Wentland 			pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
2114562236bSHarry Wentland 			if (pool->stream_enc[i] == NULL)
2124562236bSHarry Wentland 				DC_ERR("DC: failed to create stream_encoder!\n");
2134562236bSHarry Wentland 			pool->stream_enc_count++;
2144562236bSHarry Wentland 		}
2154562236bSHarry Wentland 	}
2164562236bSHarry Wentland 
2174562236bSHarry Wentland 	for (i = 0; i < num_virtual_links; i++) {
2184562236bSHarry Wentland 		pool->stream_enc[pool->stream_enc_count] =
2194562236bSHarry Wentland 			virtual_stream_encoder_create(
2204562236bSHarry Wentland 					ctx, ctx->dc_bios);
2214562236bSHarry Wentland 		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
2224562236bSHarry Wentland 			DC_ERR("DC: failed to create stream_encoder!\n");
2234562236bSHarry Wentland 			return false;
2244562236bSHarry Wentland 		}
2254562236bSHarry Wentland 		pool->stream_enc_count++;
2264562236bSHarry Wentland 	}
2274562236bSHarry Wentland 
2284562236bSHarry Wentland 	dc->hwseq = create_funcs->create_hwseq(ctx);
2294562236bSHarry Wentland 
2304562236bSHarry Wentland 	return true;
2314562236bSHarry Wentland }
2324562236bSHarry Wentland 
2334562236bSHarry Wentland 
2344562236bSHarry Wentland void resource_unreference_clock_source(
2354562236bSHarry Wentland 		struct resource_context *res_ctx,
2368c737fccSYongqiang Sun 		struct clock_source **clock_source)
2374562236bSHarry Wentland {
2384562236bSHarry Wentland 	int i;
2394562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; i++) {
2408c737fccSYongqiang Sun 		if (res_ctx->pool->clock_sources[i] != *clock_source)
2414562236bSHarry Wentland 			continue;
2424562236bSHarry Wentland 
2434562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]--;
2444562236bSHarry Wentland 
2454562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
2468c737fccSYongqiang Sun 			(*clock_source)->funcs->cs_power_down(*clock_source);
2474562236bSHarry Wentland 
2484562236bSHarry Wentland 		break;
2494562236bSHarry Wentland 	}
2504562236bSHarry Wentland 
2518c737fccSYongqiang Sun 	if (res_ctx->pool->dp_clock_source == *clock_source) {
2524562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count--;
2534562236bSHarry Wentland 
2544562236bSHarry Wentland 		if (res_ctx->dp_clock_source_ref_count == 0)
2558c737fccSYongqiang Sun 			(*clock_source)->funcs->cs_power_down(*clock_source);
2564562236bSHarry Wentland 	}
2578c737fccSYongqiang Sun 	*clock_source = NULL;
2584562236bSHarry Wentland }
2594562236bSHarry Wentland 
2604562236bSHarry Wentland void resource_reference_clock_source(
2614562236bSHarry Wentland 		struct resource_context *res_ctx,
2624562236bSHarry Wentland 		struct clock_source *clock_source)
2634562236bSHarry Wentland {
2644562236bSHarry Wentland 	int i;
2654562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; i++) {
2664562236bSHarry Wentland 		if (res_ctx->pool->clock_sources[i] != clock_source)
2674562236bSHarry Wentland 			continue;
2684562236bSHarry Wentland 
2694562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]++;
2704562236bSHarry Wentland 		break;
2714562236bSHarry Wentland 	}
2724562236bSHarry Wentland 
2734562236bSHarry Wentland 	if (res_ctx->pool->dp_clock_source == clock_source)
2744562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count++;
2754562236bSHarry Wentland }
2764562236bSHarry Wentland 
2774562236bSHarry Wentland bool resource_are_streams_timing_synchronizable(
2784562236bSHarry Wentland 	const struct core_stream *stream1,
2794562236bSHarry Wentland 	const struct core_stream *stream2)
2804562236bSHarry Wentland {
2814562236bSHarry Wentland 	if (stream1->public.timing.h_total != stream2->public.timing.h_total)
2824562236bSHarry Wentland 		return false;
2834562236bSHarry Wentland 
2844562236bSHarry Wentland 	if (stream1->public.timing.v_total != stream2->public.timing.v_total)
2854562236bSHarry Wentland 		return false;
2864562236bSHarry Wentland 
2874562236bSHarry Wentland 	if (stream1->public.timing.h_addressable
2884562236bSHarry Wentland 				!= stream2->public.timing.h_addressable)
2894562236bSHarry Wentland 		return false;
2904562236bSHarry Wentland 
2914562236bSHarry Wentland 	if (stream1->public.timing.v_addressable
2924562236bSHarry Wentland 				!= stream2->public.timing.v_addressable)
2934562236bSHarry Wentland 		return false;
2944562236bSHarry Wentland 
2954562236bSHarry Wentland 	if (stream1->public.timing.pix_clk_khz
2964562236bSHarry Wentland 				!= stream2->public.timing.pix_clk_khz)
2974562236bSHarry Wentland 		return false;
2984562236bSHarry Wentland 
2994562236bSHarry Wentland 	if (stream1->phy_pix_clk != stream2->phy_pix_clk
3007e2fe319SCharlene Liu 			&& (!dc_is_dp_signal(stream1->signal)
3017e2fe319SCharlene Liu 			|| !dc_is_dp_signal(stream2->signal)))
3024562236bSHarry Wentland 		return false;
3034562236bSHarry Wentland 
3044562236bSHarry Wentland 	return true;
3054562236bSHarry Wentland }
3064562236bSHarry Wentland 
3074562236bSHarry Wentland static bool is_sharable_clk_src(
3084562236bSHarry Wentland 	const struct pipe_ctx *pipe_with_clk_src,
3094562236bSHarry Wentland 	const struct pipe_ctx *pipe)
3104562236bSHarry Wentland {
3114562236bSHarry Wentland 	if (pipe_with_clk_src->clock_source == NULL)
3124562236bSHarry Wentland 		return false;
3134562236bSHarry Wentland 
3144562236bSHarry Wentland 	if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
3154562236bSHarry Wentland 		return false;
3164562236bSHarry Wentland 
3174562236bSHarry Wentland 	if (dc_is_dp_signal(pipe_with_clk_src->stream->signal))
3184562236bSHarry Wentland 		return false;
3194562236bSHarry Wentland 
3204562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
3214562236bSHarry Wentland 			&& dc_is_dvi_signal(pipe->stream->signal))
3224562236bSHarry Wentland 		return false;
3234562236bSHarry Wentland 
3244562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe->stream->signal)
3254562236bSHarry Wentland 			&& dc_is_dvi_signal(pipe_with_clk_src->stream->signal))
3264562236bSHarry Wentland 		return false;
3274562236bSHarry Wentland 
3284562236bSHarry Wentland 	if (!resource_are_streams_timing_synchronizable(
3294562236bSHarry Wentland 			pipe_with_clk_src->stream, pipe->stream))
3304562236bSHarry Wentland 		return false;
3314562236bSHarry Wentland 
3324562236bSHarry Wentland 	return true;
3334562236bSHarry Wentland }
3344562236bSHarry Wentland 
3354562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing(
3364562236bSHarry Wentland 					struct resource_context *res_ctx,
3374562236bSHarry Wentland 					struct pipe_ctx *pipe_ctx)
3384562236bSHarry Wentland {
3394562236bSHarry Wentland 	int i;
3404562236bSHarry Wentland 
3414562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
3424562236bSHarry Wentland 		if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
3434562236bSHarry Wentland 			return res_ctx->pipe_ctx[i].clock_source;
3444562236bSHarry Wentland 	}
3454562236bSHarry Wentland 
3464562236bSHarry Wentland 	return NULL;
3474562236bSHarry Wentland }
3484562236bSHarry Wentland 
3494562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface(
3504562236bSHarry Wentland 		enum surface_pixel_format surface_pixel_format)
3514562236bSHarry Wentland {
3524562236bSHarry Wentland 	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
3534562236bSHarry Wentland 
3544562236bSHarry Wentland 	switch (surface_pixel_format) {
3554562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
3564562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_INDEX8;
3574562236bSHarry Wentland 		break;
3584562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
3594562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
3604562236bSHarry Wentland 		break;
3614562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
3624562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
3634562236bSHarry Wentland 		break;
3644562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
3654562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
3664562236bSHarry Wentland 		break;
3678693049aSTony Cheng 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
3684562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
3694562236bSHarry Wentland 		break;
3704562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
3714562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
3724562236bSHarry Wentland 		break;
3734562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
3744562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
3754562236bSHarry Wentland 		break;
3764562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
3774562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
3784562236bSHarry Wentland 		break;
3794562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
3804562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
3814562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_FP16;
3824562236bSHarry Wentland 		break;
3834562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
3844562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
3854562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_420BPP12;
3864562236bSHarry Wentland 		break;
387ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
388ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
389ffbcd19aSVitaly Prosyak 		dal_pixel_format = PIXEL_FORMAT_420BPP15;
390ffbcd19aSVitaly Prosyak 		break;
3914562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
3924562236bSHarry Wentland 	default:
3934562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
3944562236bSHarry Wentland 		break;
3954562236bSHarry Wentland 	}
3964562236bSHarry Wentland 	return dal_pixel_format;
3974562236bSHarry Wentland }
3984562236bSHarry Wentland 
3994562236bSHarry Wentland static void rect_swap_helper(struct rect *rect)
4004562236bSHarry Wentland {
4014562236bSHarry Wentland 	uint32_t temp = 0;
4024562236bSHarry Wentland 
4034562236bSHarry Wentland 	temp = rect->height;
4044562236bSHarry Wentland 	rect->height = rect->width;
4054562236bSHarry Wentland 	rect->width = temp;
4064562236bSHarry Wentland 
4074562236bSHarry Wentland 	temp = rect->x;
4084562236bSHarry Wentland 	rect->x = rect->y;
4094562236bSHarry Wentland 	rect->y = temp;
4104562236bSHarry Wentland }
4114562236bSHarry Wentland 
412b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx)
4134562236bSHarry Wentland {
414b2d0a103SDmytro Laktyushkin 	const struct dc_surface *surface = &pipe_ctx->surface->public;
4151fbd2cfcSDmytro Laktyushkin 	const struct dc_stream *stream = &pipe_ctx->stream->public;
416b2d0a103SDmytro Laktyushkin 	struct scaler_data *data = &pipe_ctx->scl_data;
4174562236bSHarry Wentland 	struct rect clip = { 0 };
418b2d0a103SDmytro Laktyushkin 	int vpc_div = (data->format == PIXEL_FORMAT_420BPP12
419b2d0a103SDmytro Laktyushkin 			|| data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1;
4201fbd2cfcSDmytro Laktyushkin 	bool pri_split = pipe_ctx->bottom_pipe &&
4211fbd2cfcSDmytro Laktyushkin 			pipe_ctx->bottom_pipe->surface == pipe_ctx->surface;
4221fbd2cfcSDmytro Laktyushkin 	bool sec_split = pipe_ctx->top_pipe &&
4231fbd2cfcSDmytro Laktyushkin 			pipe_ctx->top_pipe->surface == pipe_ctx->surface;
4244562236bSHarry Wentland 
4257b779c99SVitaly Prosyak 	if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
4267b779c99SVitaly Prosyak 		stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) {
4277b779c99SVitaly Prosyak 		pri_split = false;
4287b779c99SVitaly Prosyak 		sec_split = false;
4297b779c99SVitaly Prosyak 	}
4304562236bSHarry Wentland 	/* The actual clip is an intersection between stream
4314562236bSHarry Wentland 	 * source and surface clip
4324562236bSHarry Wentland 	 */
4331fbd2cfcSDmytro Laktyushkin 	clip.x = stream->src.x > surface->clip_rect.x ?
4341fbd2cfcSDmytro Laktyushkin 			stream->src.x : surface->clip_rect.x;
4354562236bSHarry Wentland 
4361fbd2cfcSDmytro Laktyushkin 	clip.width = stream->src.x + stream->src.width <
4371fbd2cfcSDmytro Laktyushkin 			surface->clip_rect.x + surface->clip_rect.width ?
4381fbd2cfcSDmytro Laktyushkin 			stream->src.x + stream->src.width - clip.x :
4391fbd2cfcSDmytro Laktyushkin 			surface->clip_rect.x + surface->clip_rect.width - clip.x ;
4404562236bSHarry Wentland 
4411fbd2cfcSDmytro Laktyushkin 	clip.y = stream->src.y > surface->clip_rect.y ?
4421fbd2cfcSDmytro Laktyushkin 			stream->src.y : surface->clip_rect.y;
4434562236bSHarry Wentland 
4441fbd2cfcSDmytro Laktyushkin 	clip.height = stream->src.y + stream->src.height <
4451fbd2cfcSDmytro Laktyushkin 			surface->clip_rect.y + surface->clip_rect.height ?
4461fbd2cfcSDmytro Laktyushkin 			stream->src.y + stream->src.height - clip.y :
4471fbd2cfcSDmytro Laktyushkin 			surface->clip_rect.y + surface->clip_rect.height - clip.y ;
4484562236bSHarry Wentland 
4491fbd2cfcSDmytro Laktyushkin 	/* offset = src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio
4504562236bSHarry Wentland 	 * num_pixels = clip.num_pix * scl_ratio
4514562236bSHarry Wentland 	 */
4521fbd2cfcSDmytro Laktyushkin 	data->viewport.x = surface->src_rect.x + (clip.x - surface->dst_rect.x) *
4531fbd2cfcSDmytro Laktyushkin 			surface->src_rect.width / surface->dst_rect.width;
454b2d0a103SDmytro Laktyushkin 	data->viewport.width = clip.width *
4551fbd2cfcSDmytro Laktyushkin 			surface->src_rect.width / surface->dst_rect.width;
4564562236bSHarry Wentland 
4571fbd2cfcSDmytro Laktyushkin 	data->viewport.y = surface->src_rect.y + (clip.y - surface->dst_rect.y) *
4581fbd2cfcSDmytro Laktyushkin 			surface->src_rect.height / surface->dst_rect.height;
459b2d0a103SDmytro Laktyushkin 	data->viewport.height = clip.height *
4601fbd2cfcSDmytro Laktyushkin 			surface->src_rect.height / surface->dst_rect.height;
4614562236bSHarry Wentland 
462b2d0a103SDmytro Laktyushkin 	/* Round down, compensate in init */
463b2d0a103SDmytro Laktyushkin 	data->viewport_c.x = data->viewport.x / vpc_div;
464b2d0a103SDmytro Laktyushkin 	data->viewport_c.y = data->viewport.y / vpc_div;
465b2d0a103SDmytro Laktyushkin 	data->inits.h_c = (data->viewport.x % vpc_div) != 0 ?
466b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_half : dal_fixed31_32_zero;
467b2d0a103SDmytro Laktyushkin 	data->inits.v_c = (data->viewport.y % vpc_div) != 0 ?
468b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_half : dal_fixed31_32_zero;
469b2d0a103SDmytro Laktyushkin 	/* Round up, assume original video size always even dimensions */
470b2d0a103SDmytro Laktyushkin 	data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div;
471b2d0a103SDmytro Laktyushkin 	data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div;
472b2d0a103SDmytro Laktyushkin 
473b2d0a103SDmytro Laktyushkin 	/* Handle hsplit */
4741fbd2cfcSDmytro Laktyushkin 	if (pri_split || sec_split) {
4751fbd2cfcSDmytro Laktyushkin 		/* HMirror XOR Secondary_pipe XOR Rotation_180 */
4761fbd2cfcSDmytro Laktyushkin 		bool right_view = (sec_split != surface->horizontal_mirror) !=
4771fbd2cfcSDmytro Laktyushkin 					(surface->rotation == ROTATION_ANGLE_180);
4789e6c74ceSDmytro Laktyushkin 
4791fbd2cfcSDmytro Laktyushkin 		if (surface->rotation == ROTATION_ANGLE_90
4801fbd2cfcSDmytro Laktyushkin 				|| surface->rotation == ROTATION_ANGLE_270)
4811fbd2cfcSDmytro Laktyushkin 			/* Secondary_pipe XOR Rotation_270 */
4821fbd2cfcSDmytro Laktyushkin 			right_view = (surface->rotation == ROTATION_ANGLE_270) != sec_split;
4839e6c74ceSDmytro Laktyushkin 
4849e6c74ceSDmytro Laktyushkin 		if (right_view) {
485b2d0a103SDmytro Laktyushkin 			data->viewport.width /= 2;
486b2d0a103SDmytro Laktyushkin 			data->viewport_c.width /= 2;
487b2d0a103SDmytro Laktyushkin 			data->viewport.x +=  data->viewport.width;
488b2d0a103SDmytro Laktyushkin 			data->viewport_c.x +=  data->viewport_c.width;
4899e6c74ceSDmytro Laktyushkin 			/* Ceil offset pipe */
490b2d0a103SDmytro Laktyushkin 			data->viewport.width += data->viewport.width % 2;
491b2d0a103SDmytro Laktyushkin 			data->viewport_c.width += data->viewport_c.width % 2;
4929e6c74ceSDmytro Laktyushkin 		} else {
493b2d0a103SDmytro Laktyushkin 			data->viewport.width /= 2;
494b2d0a103SDmytro Laktyushkin 			data->viewport_c.width /= 2;
495b2d0a103SDmytro Laktyushkin 		}
4964562236bSHarry Wentland 	}
4971fbd2cfcSDmytro Laktyushkin 
4981fbd2cfcSDmytro Laktyushkin 	if (surface->rotation == ROTATION_ANGLE_90 ||
4991fbd2cfcSDmytro Laktyushkin 			surface->rotation == ROTATION_ANGLE_270) {
5001fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport_c);
5011fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport);
5021fbd2cfcSDmytro Laktyushkin 	}
5039e6c74ceSDmytro Laktyushkin }
5044562236bSHarry Wentland 
505b2d0a103SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip)
5064562236bSHarry Wentland {
507b2d0a103SDmytro Laktyushkin 	const struct dc_surface *surface = &pipe_ctx->surface->public;
5084562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
5094562236bSHarry Wentland 	struct rect clip = surface->clip_rect;
510c802570eSDmytro Laktyushkin 	int recout_full_x, recout_full_y;
5114562236bSHarry Wentland 
5124562236bSHarry Wentland 	pipe_ctx->scl_data.recout.x = stream->public.dst.x;
5134562236bSHarry Wentland 	if (stream->public.src.x < clip.x)
5144562236bSHarry Wentland 		pipe_ctx->scl_data.recout.x += (clip.x
5154562236bSHarry Wentland 			- stream->public.src.x) * stream->public.dst.width
5164562236bSHarry Wentland 						/ stream->public.src.width;
5174562236bSHarry Wentland 
5184562236bSHarry Wentland 	pipe_ctx->scl_data.recout.width = clip.width *
5194562236bSHarry Wentland 			stream->public.dst.width / stream->public.src.width;
5204562236bSHarry Wentland 	if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x >
5214562236bSHarry Wentland 			stream->public.dst.x + stream->public.dst.width)
5224562236bSHarry Wentland 		pipe_ctx->scl_data.recout.width =
5234562236bSHarry Wentland 			stream->public.dst.x + stream->public.dst.width
5244562236bSHarry Wentland 						- pipe_ctx->scl_data.recout.x;
5254562236bSHarry Wentland 
5264562236bSHarry Wentland 	pipe_ctx->scl_data.recout.y = stream->public.dst.y;
5274562236bSHarry Wentland 	if (stream->public.src.y < clip.y)
5284562236bSHarry Wentland 		pipe_ctx->scl_data.recout.y += (clip.y
5294562236bSHarry Wentland 			- stream->public.src.y) * stream->public.dst.height
5304562236bSHarry Wentland 						/ stream->public.src.height;
5314562236bSHarry Wentland 
5324562236bSHarry Wentland 	pipe_ctx->scl_data.recout.height = clip.height *
5334562236bSHarry Wentland 			stream->public.dst.height / stream->public.src.height;
5344562236bSHarry Wentland 	if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y >
5354562236bSHarry Wentland 			stream->public.dst.y + stream->public.dst.height)
5364562236bSHarry Wentland 		pipe_ctx->scl_data.recout.height =
5374562236bSHarry Wentland 			stream->public.dst.y + stream->public.dst.height
5384562236bSHarry Wentland 						- pipe_ctx->scl_data.recout.y;
539b2d0a103SDmytro Laktyushkin 
5407b779c99SVitaly Prosyak 	/* Handle h & vsplit */
5417b779c99SVitaly Prosyak 	if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface ==
5427b779c99SVitaly Prosyak 		pipe_ctx->surface) {
5437b779c99SVitaly Prosyak 		if (stream->public.timing.timing_3d_format ==
5447b779c99SVitaly Prosyak 			TIMING_3D_FORMAT_TOP_AND_BOTTOM) {
5457b779c99SVitaly Prosyak 			pipe_ctx->scl_data.recout.height /= 2;
5467b779c99SVitaly Prosyak 			pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height;
5477b779c99SVitaly Prosyak 			/* Floor primary pipe, ceil 2ndary pipe */
5487b779c99SVitaly Prosyak 			pipe_ctx->scl_data.recout.height += pipe_ctx->scl_data.recout.height % 2;
5497b779c99SVitaly Prosyak 		} else {
550b2d0a103SDmytro Laktyushkin 			pipe_ctx->scl_data.recout.width /= 2;
551b2d0a103SDmytro Laktyushkin 			pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width;
552b2d0a103SDmytro Laktyushkin 			pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2;
5537b779c99SVitaly Prosyak 		}
5547b779c99SVitaly Prosyak 	} else if (pipe_ctx->bottom_pipe &&
5557b779c99SVitaly Prosyak 			   pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) {
5567b779c99SVitaly Prosyak 		if (stream->public.timing.timing_3d_format ==
5577b779c99SVitaly Prosyak 			TIMING_3D_FORMAT_TOP_AND_BOTTOM)
5587b779c99SVitaly Prosyak 			pipe_ctx->scl_data.recout.height /= 2;
5597b779c99SVitaly Prosyak 		else
560b2d0a103SDmytro Laktyushkin 			pipe_ctx->scl_data.recout.width /= 2;
5614562236bSHarry Wentland 	}
5624562236bSHarry Wentland 
563c802570eSDmytro Laktyushkin 	/* Unclipped recout offset = stream dst offset + ((surf dst offset - stream src offset)
564c802570eSDmytro Laktyushkin 	 * 				* 1/ stream scaling ratio) - (surf src offset * 1/ full scl
565c802570eSDmytro Laktyushkin 	 * 				ratio)
566c802570eSDmytro Laktyushkin 	 */
567c802570eSDmytro Laktyushkin 	recout_full_x = stream->public.dst.x + (surface->dst_rect.x -  stream->public.src.x)
568c802570eSDmytro Laktyushkin 					* stream->public.dst.width / stream->public.src.width -
569c802570eSDmytro Laktyushkin 			surface->src_rect.x * surface->dst_rect.width / surface->src_rect.width
570c802570eSDmytro Laktyushkin 					* stream->public.dst.width / stream->public.src.width;
571c802570eSDmytro Laktyushkin 	recout_full_y = stream->public.dst.y + (surface->dst_rect.y -  stream->public.src.y)
572c802570eSDmytro Laktyushkin 					* stream->public.dst.height / stream->public.src.height -
573c802570eSDmytro Laktyushkin 			surface->src_rect.y * surface->dst_rect.height / surface->src_rect.height
574c802570eSDmytro Laktyushkin 					* stream->public.dst.height / stream->public.src.height;
575c802570eSDmytro Laktyushkin 
576c802570eSDmytro Laktyushkin 	recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x;
577c802570eSDmytro Laktyushkin 	recout_skip->height = pipe_ctx->scl_data.recout.y - recout_full_y;
578b2d0a103SDmytro Laktyushkin }
579b2d0a103SDmytro Laktyushkin 
580b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
5814562236bSHarry Wentland {
582b2d0a103SDmytro Laktyushkin 	const struct dc_surface *surface = &pipe_ctx->surface->public;
5834562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
5841fbd2cfcSDmytro Laktyushkin 	const int in_w = stream->public.src.width;
5851fbd2cfcSDmytro Laktyushkin 	const int in_h = stream->public.src.height;
5861fbd2cfcSDmytro Laktyushkin 	const int out_w = stream->public.dst.width;
5871fbd2cfcSDmytro Laktyushkin 	const int out_h = stream->public.dst.height;
5884562236bSHarry Wentland 
5894562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction(
5904562236bSHarry Wentland 					surface->src_rect.width,
5914562236bSHarry Wentland 					surface->dst_rect.width);
5924562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction(
5934562236bSHarry Wentland 					surface->src_rect.height,
5944562236bSHarry Wentland 					surface->dst_rect.height);
5954562236bSHarry Wentland 
5964562236bSHarry Wentland 	if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
5974562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz.value *= 2;
5984562236bSHarry Wentland 	else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
5994562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert.value *= 2;
6004562236bSHarry Wentland 
6014562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert.value = div64_s64(
6024562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert.value * in_h, out_h);
6034562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz.value = div64_s64(
6044562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz.value * in_w, out_w);
6054562236bSHarry Wentland 
6064562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz;
6074562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert;
6084562236bSHarry Wentland 
609b2d0a103SDmytro Laktyushkin 	if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12
610b2d0a103SDmytro Laktyushkin 			|| pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP15) {
6114562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz_c.value /= 2;
6124562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert_c.value /= 2;
6134562236bSHarry Wentland 	}
6144562236bSHarry Wentland }
6154562236bSHarry Wentland 
616b2d0a103SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip)
6174562236bSHarry Wentland {
618b2d0a103SDmytro Laktyushkin 	struct scaler_data *data = &pipe_ctx->scl_data;
619b2d0a103SDmytro Laktyushkin 	struct rect src = pipe_ctx->surface->public.src_rect;
620b2d0a103SDmytro Laktyushkin 	int vpc_div = (data->format == PIXEL_FORMAT_420BPP12
621b2d0a103SDmytro Laktyushkin 			|| data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1;
622b2d0a103SDmytro Laktyushkin 
6231fbd2cfcSDmytro Laktyushkin 	if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 ||
6241fbd2cfcSDmytro Laktyushkin 			pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) {
6251fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport_c);
6261fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport);
6271fbd2cfcSDmytro Laktyushkin 	}
6281fbd2cfcSDmytro Laktyushkin 
629b2d0a103SDmytro Laktyushkin 	/*
630b2d0a103SDmytro Laktyushkin 	 * Init calculated according to formula:
631b2d0a103SDmytro Laktyushkin 	 * 	init = (scaling_ratio + number_of_taps + 1) / 2
632b2d0a103SDmytro Laktyushkin 	 * 	init_bot = init + scaling_ratio
633b2d0a103SDmytro Laktyushkin 	 * 	init_c = init + truncated_vp_c_offset(from calculate viewport)
634b2d0a103SDmytro Laktyushkin 	 */
635b2d0a103SDmytro Laktyushkin 	data->inits.h = dal_fixed31_32_div_int(
636b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2);
637b2d0a103SDmytro Laktyushkin 
638b2d0a103SDmytro Laktyushkin 	data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int(
639b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2));
640b2d0a103SDmytro Laktyushkin 
641b2d0a103SDmytro Laktyushkin 	data->inits.v = dal_fixed31_32_div_int(
642b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2);
643b2d0a103SDmytro Laktyushkin 
644b2d0a103SDmytro Laktyushkin 	data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int(
645b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2));
646b2d0a103SDmytro Laktyushkin 
647b2d0a103SDmytro Laktyushkin 
648b2d0a103SDmytro Laktyushkin 	/* Adjust for viewport end clip-off */
649b2d0a103SDmytro Laktyushkin 	if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) {
650b2d0a103SDmytro Laktyushkin 		int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x;
6511fbd2cfcSDmytro Laktyushkin 		int int_part = dal_fixed31_32_floor(
6521fbd2cfcSDmytro Laktyushkin 				dal_fixed31_32_sub(data->inits.h, data->ratios.horz));
653b2d0a103SDmytro Laktyushkin 
6541fbd2cfcSDmytro Laktyushkin 		int_part = int_part > 0 ? int_part : 0;
655b2d0a103SDmytro Laktyushkin 		data->viewport.width += int_part < vp_clip ? int_part : vp_clip;
656b2d0a103SDmytro Laktyushkin 	}
657b2d0a103SDmytro Laktyushkin 	if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) {
658b2d0a103SDmytro Laktyushkin 		int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y;
6591fbd2cfcSDmytro Laktyushkin 		int int_part = dal_fixed31_32_floor(
6601fbd2cfcSDmytro Laktyushkin 				dal_fixed31_32_sub(data->inits.v, data->ratios.vert));
661b2d0a103SDmytro Laktyushkin 
6621fbd2cfcSDmytro Laktyushkin 		int_part = int_part > 0 ? int_part : 0;
663b2d0a103SDmytro Laktyushkin 		data->viewport.height += int_part < vp_clip ? int_part : vp_clip;
664b2d0a103SDmytro Laktyushkin 	}
665b2d0a103SDmytro Laktyushkin 	if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) {
666b2d0a103SDmytro Laktyushkin 		int vp_clip = (src.x + src.width) / vpc_div -
667b2d0a103SDmytro Laktyushkin 				data->viewport_c.width - data->viewport_c.x;
6681fbd2cfcSDmytro Laktyushkin 		int int_part = dal_fixed31_32_floor(
6691fbd2cfcSDmytro Laktyushkin 				dal_fixed31_32_sub(data->inits.h_c, data->ratios.horz_c));
670b2d0a103SDmytro Laktyushkin 
6711fbd2cfcSDmytro Laktyushkin 		int_part = int_part > 0 ? int_part : 0;
672b2d0a103SDmytro Laktyushkin 		data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip;
673b2d0a103SDmytro Laktyushkin 	}
674b2d0a103SDmytro Laktyushkin 	if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) {
675b2d0a103SDmytro Laktyushkin 		int vp_clip = (src.y + src.height) / vpc_div -
676b2d0a103SDmytro Laktyushkin 				data->viewport_c.height - data->viewport_c.y;
6771fbd2cfcSDmytro Laktyushkin 		int int_part = dal_fixed31_32_floor(
6781fbd2cfcSDmytro Laktyushkin 				dal_fixed31_32_sub(data->inits.v_c, data->ratios.vert_c));
679b2d0a103SDmytro Laktyushkin 
6801fbd2cfcSDmytro Laktyushkin 		int_part = int_part > 0 ? int_part : 0;
681b2d0a103SDmytro Laktyushkin 		data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip;
682b2d0a103SDmytro Laktyushkin 	}
683b2d0a103SDmytro Laktyushkin 
684b2d0a103SDmytro Laktyushkin 	/* Adjust for non-0 viewport offset */
685b2d0a103SDmytro Laktyushkin 	if (data->viewport.x) {
686b2d0a103SDmytro Laktyushkin 		int int_part;
687b2d0a103SDmytro Laktyushkin 
688b2d0a103SDmytro Laktyushkin 		data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int(
689b2d0a103SDmytro Laktyushkin 				data->ratios.horz, recout_skip->width));
690b2d0a103SDmytro Laktyushkin 		int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x;
691b2d0a103SDmytro Laktyushkin 		if (int_part < data->taps.h_taps) {
692b2d0a103SDmytro Laktyushkin 			int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ?
693b2d0a103SDmytro Laktyushkin 						(data->taps.h_taps - int_part) : data->viewport.x;
694b2d0a103SDmytro Laktyushkin 			data->viewport.x -= int_adj;
695b2d0a103SDmytro Laktyushkin 			data->viewport.width += int_adj;
696b2d0a103SDmytro Laktyushkin 			int_part += int_adj;
697b2d0a103SDmytro Laktyushkin 		} else if (int_part > data->taps.h_taps) {
698b2d0a103SDmytro Laktyushkin 			data->viewport.x += int_part - data->taps.h_taps;
699b2d0a103SDmytro Laktyushkin 			data->viewport.width -= int_part - data->taps.h_taps;
700b2d0a103SDmytro Laktyushkin 			int_part = data->taps.h_taps;
701b2d0a103SDmytro Laktyushkin 		}
702b2d0a103SDmytro Laktyushkin 		data->inits.h.value &= 0xffffffff;
703b2d0a103SDmytro Laktyushkin 		data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part);
704b2d0a103SDmytro Laktyushkin 	}
705b2d0a103SDmytro Laktyushkin 
706b2d0a103SDmytro Laktyushkin 	if (data->viewport_c.x) {
707b2d0a103SDmytro Laktyushkin 		int int_part;
708b2d0a103SDmytro Laktyushkin 
709b2d0a103SDmytro Laktyushkin 		data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int(
710b2d0a103SDmytro Laktyushkin 				data->ratios.horz_c, recout_skip->width));
711b2d0a103SDmytro Laktyushkin 		int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x;
712b2d0a103SDmytro Laktyushkin 		if (int_part < data->taps.h_taps_c) {
713b2d0a103SDmytro Laktyushkin 			int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ?
714b2d0a103SDmytro Laktyushkin 					(data->taps.h_taps_c - int_part) : data->viewport_c.x;
715b2d0a103SDmytro Laktyushkin 			data->viewport_c.x -= int_adj;
716b2d0a103SDmytro Laktyushkin 			data->viewport_c.width += int_adj;
717b2d0a103SDmytro Laktyushkin 			int_part += int_adj;
718b2d0a103SDmytro Laktyushkin 		} else if (int_part > data->taps.h_taps_c) {
719b2d0a103SDmytro Laktyushkin 			data->viewport_c.x += int_part - data->taps.h_taps_c;
720b2d0a103SDmytro Laktyushkin 			data->viewport_c.width -= int_part - data->taps.h_taps_c;
721b2d0a103SDmytro Laktyushkin 			int_part = data->taps.h_taps_c;
722b2d0a103SDmytro Laktyushkin 		}
723b2d0a103SDmytro Laktyushkin 		data->inits.h_c.value &= 0xffffffff;
724b2d0a103SDmytro Laktyushkin 		data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part);
725b2d0a103SDmytro Laktyushkin 	}
726b2d0a103SDmytro Laktyushkin 
727b2d0a103SDmytro Laktyushkin 	if (data->viewport.y) {
728b2d0a103SDmytro Laktyushkin 		int int_part;
729b2d0a103SDmytro Laktyushkin 
730b2d0a103SDmytro Laktyushkin 		data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int(
731b2d0a103SDmytro Laktyushkin 				data->ratios.vert, recout_skip->height));
732b2d0a103SDmytro Laktyushkin 		int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y;
733b2d0a103SDmytro Laktyushkin 		if (int_part < data->taps.v_taps) {
734b2d0a103SDmytro Laktyushkin 			int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ?
735b2d0a103SDmytro Laktyushkin 						(data->taps.v_taps - int_part) : data->viewport.y;
736b2d0a103SDmytro Laktyushkin 			data->viewport.y -= int_adj;
737b2d0a103SDmytro Laktyushkin 			data->viewport.height += int_adj;
738b2d0a103SDmytro Laktyushkin 			int_part += int_adj;
739b2d0a103SDmytro Laktyushkin 		} else if (int_part > data->taps.v_taps) {
740b2d0a103SDmytro Laktyushkin 			data->viewport.y += int_part - data->taps.v_taps;
741b2d0a103SDmytro Laktyushkin 			data->viewport.height -= int_part - data->taps.v_taps;
742b2d0a103SDmytro Laktyushkin 			int_part = data->taps.v_taps;
743b2d0a103SDmytro Laktyushkin 		}
744b2d0a103SDmytro Laktyushkin 		data->inits.v.value &= 0xffffffff;
745b2d0a103SDmytro Laktyushkin 		data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part);
746b2d0a103SDmytro Laktyushkin 	}
747b2d0a103SDmytro Laktyushkin 
748b2d0a103SDmytro Laktyushkin 	if (data->viewport_c.y) {
749b2d0a103SDmytro Laktyushkin 		int int_part;
750b2d0a103SDmytro Laktyushkin 
751b2d0a103SDmytro Laktyushkin 		data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int(
752b2d0a103SDmytro Laktyushkin 				data->ratios.vert_c, recout_skip->height));
753b2d0a103SDmytro Laktyushkin 		int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y;
754b2d0a103SDmytro Laktyushkin 		if (int_part < data->taps.v_taps_c) {
755b2d0a103SDmytro Laktyushkin 			int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ?
756b2d0a103SDmytro Laktyushkin 					(data->taps.v_taps_c - int_part) : data->viewport_c.y;
757b2d0a103SDmytro Laktyushkin 			data->viewport_c.y -= int_adj;
758b2d0a103SDmytro Laktyushkin 			data->viewport_c.height += int_adj;
759b2d0a103SDmytro Laktyushkin 			int_part += int_adj;
760b2d0a103SDmytro Laktyushkin 		} else if (int_part > data->taps.v_taps_c) {
761b2d0a103SDmytro Laktyushkin 			data->viewport_c.y += int_part - data->taps.v_taps_c;
762b2d0a103SDmytro Laktyushkin 			data->viewport_c.height -= int_part - data->taps.v_taps_c;
763b2d0a103SDmytro Laktyushkin 			int_part = data->taps.v_taps_c;
764b2d0a103SDmytro Laktyushkin 		}
765b2d0a103SDmytro Laktyushkin 		data->inits.v_c.value &= 0xffffffff;
766b2d0a103SDmytro Laktyushkin 		data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part);
767b2d0a103SDmytro Laktyushkin 	}
768b2d0a103SDmytro Laktyushkin 
769b2d0a103SDmytro Laktyushkin 	/* Interlaced inits based on final vert inits */
770b2d0a103SDmytro Laktyushkin 	data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert);
771b2d0a103SDmytro Laktyushkin 	data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c);
7721fbd2cfcSDmytro Laktyushkin 
7731fbd2cfcSDmytro Laktyushkin 	if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 ||
7741fbd2cfcSDmytro Laktyushkin 			pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) {
7751fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport_c);
7761fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport);
7771fbd2cfcSDmytro Laktyushkin 	}
778b2d0a103SDmytro Laktyushkin }
779b2d0a103SDmytro Laktyushkin 
780b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
781b2d0a103SDmytro Laktyushkin {
782b2d0a103SDmytro Laktyushkin 	const struct dc_surface *surface = &pipe_ctx->surface->public;
7834562236bSHarry Wentland 	struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
784b2d0a103SDmytro Laktyushkin 	struct view recout_skip = { 0 };
785b2d0a103SDmytro Laktyushkin 	bool res = false;
786b2d0a103SDmytro Laktyushkin 
7874562236bSHarry Wentland 	/* Important: scaling ratio calculation requires pixel format,
7884562236bSHarry Wentland 	 * lb depth calculation requires recout and taps require scaling ratios.
789b2d0a103SDmytro Laktyushkin 	 * Inits require viewport, taps, ratios and recout of split pipe
7904562236bSHarry Wentland 	 */
791b2d0a103SDmytro Laktyushkin 	pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(
792b2d0a103SDmytro Laktyushkin 			pipe_ctx->surface->public.format);
7934562236bSHarry Wentland 
794b2d0a103SDmytro Laktyushkin 	calculate_scaling_ratios(pipe_ctx);
795b2d0a103SDmytro Laktyushkin 
796b2d0a103SDmytro Laktyushkin 	calculate_viewport(pipe_ctx);
7974562236bSHarry Wentland 
7984562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16)
7994562236bSHarry Wentland 		return false;
8004562236bSHarry Wentland 
801b2d0a103SDmytro Laktyushkin 	calculate_recout(pipe_ctx, &recout_skip);
8024562236bSHarry Wentland 
8034562236bSHarry Wentland 	/**
8044562236bSHarry Wentland 	 * Setting line buffer pixel depth to 24bpp yields banding
8054562236bSHarry Wentland 	 * on certain displays, such as the Sharp 4k
8064562236bSHarry Wentland 	 */
8074562236bSHarry Wentland 	pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
8084562236bSHarry Wentland 
8094562236bSHarry Wentland 	pipe_ctx->scl_data.h_active = timing->h_addressable;
8104562236bSHarry Wentland 	pipe_ctx->scl_data.v_active = timing->v_addressable;
8114562236bSHarry Wentland 
8124562236bSHarry Wentland 	/* Taps calculations */
8134562236bSHarry Wentland 	res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
8144562236bSHarry Wentland 		pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
8154562236bSHarry Wentland 
8164562236bSHarry Wentland 	if (!res) {
8174562236bSHarry Wentland 		/* Try 24 bpp linebuffer */
8184562236bSHarry Wentland 		pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
8194562236bSHarry Wentland 
8204562236bSHarry Wentland 		res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
8214562236bSHarry Wentland 			pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
8224562236bSHarry Wentland 	}
8234562236bSHarry Wentland 
824b2d0a103SDmytro Laktyushkin 	if (res)
8251fbd2cfcSDmytro Laktyushkin 		/* May need to re-check lb size after this in some obscure scenario */
826b2d0a103SDmytro Laktyushkin 		calculate_inits_and_adj_vp(pipe_ctx, &recout_skip);
827b2d0a103SDmytro Laktyushkin 
8284562236bSHarry Wentland 	dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
8294562236bSHarry Wentland 				"%s: Viewport:\nheight:%d width:%d x:%d "
8304562236bSHarry Wentland 				"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
8314562236bSHarry Wentland 				"y:%d\n",
8324562236bSHarry Wentland 				__func__,
8334562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.height,
8344562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.width,
8354562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.x,
8364562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.y,
8374562236bSHarry Wentland 				surface->dst_rect.height,
8384562236bSHarry Wentland 				surface->dst_rect.width,
8394562236bSHarry Wentland 				surface->dst_rect.x,
8404562236bSHarry Wentland 				surface->dst_rect.y);
8414562236bSHarry Wentland 
8424562236bSHarry Wentland 	return res;
8434562236bSHarry Wentland }
8444562236bSHarry Wentland 
8454562236bSHarry Wentland 
8464562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context(
8474562236bSHarry Wentland 	const struct core_dc *dc,
8484562236bSHarry Wentland 	struct validate_context *context)
8494562236bSHarry Wentland {
8504562236bSHarry Wentland 	int i;
8514562236bSHarry Wentland 
8524562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
8534562236bSHarry Wentland 		if (context->res_ctx.pipe_ctx[i].surface != NULL &&
8544562236bSHarry Wentland 				context->res_ctx.pipe_ctx[i].stream != NULL)
855b2d0a103SDmytro Laktyushkin 			if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i]))
856f84a8161STony Cheng 				return DC_FAIL_SCALING;
8574562236bSHarry Wentland 	}
8584562236bSHarry Wentland 
8594562236bSHarry Wentland 	return DC_OK;
8604562236bSHarry Wentland }
8614562236bSHarry Wentland 
862ab2541b6SAric Cyr static void detach_surfaces_for_stream(
8634562236bSHarry Wentland 		struct validate_context *context,
864ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
8654562236bSHarry Wentland {
8664562236bSHarry Wentland 	int i;
867ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
8684562236bSHarry Wentland 
8694562236bSHarry Wentland 	for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
8704562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i];
8714562236bSHarry Wentland 		if (cur_pipe->stream == stream) {
8724562236bSHarry Wentland 			cur_pipe->surface = NULL;
8734562236bSHarry Wentland 			cur_pipe->top_pipe = NULL;
8744562236bSHarry Wentland 			cur_pipe->bottom_pipe = NULL;
8754562236bSHarry Wentland 		}
8764562236bSHarry Wentland 	}
8774562236bSHarry Wentland }
8784562236bSHarry Wentland 
8794562236bSHarry Wentland struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx)
8804562236bSHarry Wentland {
8814562236bSHarry Wentland 	int i;
8824562236bSHarry Wentland 	struct pipe_ctx *secondary_pipe = NULL;
8834562236bSHarry Wentland 
8844562236bSHarry Wentland 	/*
8854562236bSHarry Wentland 	 * search backwards for the second pipe to keep pipe
8864562236bSHarry Wentland 	 * assignment more consistent
8874562236bSHarry Wentland 	 */
8884562236bSHarry Wentland 
8894562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
8904562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == NULL) {
8914562236bSHarry Wentland 			secondary_pipe = &res_ctx->pipe_ctx[i];
8924562236bSHarry Wentland 			secondary_pipe->pipe_idx = i;
8934562236bSHarry Wentland 			break;
8944562236bSHarry Wentland 		}
8954562236bSHarry Wentland 	}
8964562236bSHarry Wentland 
8974562236bSHarry Wentland 
8984562236bSHarry Wentland 	return secondary_pipe;
8994562236bSHarry Wentland }
9004562236bSHarry Wentland 
9014562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream(
9024562236bSHarry Wentland 		struct resource_context *res_ctx,
9034562236bSHarry Wentland 		const struct core_stream *stream)
9044562236bSHarry Wentland {
9054562236bSHarry Wentland 	int i;
9064562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->pipe_count; i++) {
9074562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
908e73c1efcSYongqiang Sun 				res_ctx->pipe_ctx[i].stream_enc) {
9094562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
9104562236bSHarry Wentland 			break;
9114562236bSHarry Wentland 		}
9124562236bSHarry Wentland 	}
9134562236bSHarry Wentland 	return NULL;
9144562236bSHarry Wentland }
9154562236bSHarry Wentland 
9164562236bSHarry Wentland /*
917ab2541b6SAric Cyr  * A free_pipe for a stream is defined here as a pipe
918ab2541b6SAric Cyr  * that has no surface attached yet
9194562236bSHarry Wentland  */
920ab2541b6SAric Cyr static struct pipe_ctx *acquire_free_pipe_for_stream(
921745cc746SDmytro Laktyushkin 		struct validate_context *context,
922ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
9234562236bSHarry Wentland {
9244562236bSHarry Wentland 	int i;
925745cc746SDmytro Laktyushkin 	struct resource_context *res_ctx = &context->res_ctx;
926ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
9274562236bSHarry Wentland 
9284562236bSHarry Wentland 	struct pipe_ctx *head_pipe = NULL;
9294562236bSHarry Wentland 
9304562236bSHarry Wentland 	/* Find head pipe, which has the back end set up*/
9314562236bSHarry Wentland 
9324562236bSHarry Wentland 	head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
9334562236bSHarry Wentland 
9344562236bSHarry Wentland 	if (!head_pipe)
9354562236bSHarry Wentland 		ASSERT(0);
9364562236bSHarry Wentland 
9374562236bSHarry Wentland 	if (!head_pipe->surface)
9384562236bSHarry Wentland 		return head_pipe;
9394562236bSHarry Wentland 
9404562236bSHarry Wentland 	/* Re-use pipe already acquired for this stream if available*/
9414562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
9424562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
9434562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].surface) {
9444562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
9454562236bSHarry Wentland 		}
9464562236bSHarry Wentland 	}
9474562236bSHarry Wentland 
9484562236bSHarry Wentland 	/*
9494562236bSHarry Wentland 	 * At this point we have no re-useable pipe for this stream and we need
9504562236bSHarry Wentland 	 * to acquire an idle one to satisfy the request
9514562236bSHarry Wentland 	 */
9524562236bSHarry Wentland 
9534562236bSHarry Wentland 	if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer)
9544562236bSHarry Wentland 		return NULL;
9554562236bSHarry Wentland 
956745cc746SDmytro Laktyushkin 	return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(context, stream);
9574562236bSHarry Wentland 
9584562236bSHarry Wentland }
9594562236bSHarry Wentland 
960ab2541b6SAric Cyr static void release_free_pipes_for_stream(
9614562236bSHarry Wentland 		struct resource_context *res_ctx,
962ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
9634562236bSHarry Wentland {
9644562236bSHarry Wentland 	int i;
965ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
9664562236bSHarry Wentland 
9674562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
9684562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
9694562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].surface) {
9704562236bSHarry Wentland 			res_ctx->pipe_ctx[i].stream = NULL;
9714562236bSHarry Wentland 		}
9724562236bSHarry Wentland 	}
9734562236bSHarry Wentland }
9744562236bSHarry Wentland 
9754562236bSHarry Wentland bool resource_attach_surfaces_to_context(
9764562236bSHarry Wentland 		const struct dc_surface * const *surfaces,
9774562236bSHarry Wentland 		int surface_count,
978ab2541b6SAric Cyr 		const struct dc_stream *dc_stream,
9794562236bSHarry Wentland 		struct validate_context *context)
9804562236bSHarry Wentland {
9814562236bSHarry Wentland 	int i;
9824562236bSHarry Wentland 	struct pipe_ctx *tail_pipe;
983ab2541b6SAric Cyr 	struct dc_stream_status *stream_status = NULL;
9844562236bSHarry Wentland 
9854562236bSHarry Wentland 
9864562236bSHarry Wentland 	if (surface_count > MAX_SURFACE_NUM) {
9874562236bSHarry Wentland 		dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
9884562236bSHarry Wentland 			surface_count, MAX_SURFACE_NUM);
9894562236bSHarry Wentland 		return false;
9904562236bSHarry Wentland 	}
9914562236bSHarry Wentland 
992ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++)
993ab2541b6SAric Cyr 		if (&context->streams[i]->public == dc_stream) {
994ab2541b6SAric Cyr 			stream_status = &context->stream_status[i];
9954562236bSHarry Wentland 			break;
9964562236bSHarry Wentland 		}
997ab2541b6SAric Cyr 	if (stream_status == NULL) {
998ab2541b6SAric Cyr 		dm_error("Existing stream not found; failed to attach surfaces\n");
9994562236bSHarry Wentland 		return false;
10004562236bSHarry Wentland 	}
10014562236bSHarry Wentland 
10024562236bSHarry Wentland 	/* retain new surfaces */
10034562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
10044562236bSHarry Wentland 		dc_surface_retain(surfaces[i]);
10054562236bSHarry Wentland 
1006ab2541b6SAric Cyr 	detach_surfaces_for_stream(context, dc_stream);
10074562236bSHarry Wentland 
10084562236bSHarry Wentland 	/* release existing surfaces*/
1009ab2541b6SAric Cyr 	for (i = 0; i < stream_status->surface_count; i++)
1010ab2541b6SAric Cyr 		dc_surface_release(stream_status->surfaces[i]);
10114562236bSHarry Wentland 
1012ab2541b6SAric Cyr 	for (i = surface_count; i < stream_status->surface_count; i++)
1013ab2541b6SAric Cyr 		stream_status->surfaces[i] = NULL;
10144562236bSHarry Wentland 
1015ab2541b6SAric Cyr 	stream_status->surface_count = 0;
10164562236bSHarry Wentland 
10174562236bSHarry Wentland 	if (surface_count == 0)
10184562236bSHarry Wentland 		return true;
10194562236bSHarry Wentland 
10204562236bSHarry Wentland 	tail_pipe = NULL;
10214562236bSHarry Wentland 	for (i = 0; i < surface_count; i++) {
10224562236bSHarry Wentland 		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
1023745cc746SDmytro Laktyushkin 		struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(context, dc_stream);
10244562236bSHarry Wentland 
10254562236bSHarry Wentland 		if (!free_pipe) {
1026ab2541b6SAric Cyr 			stream_status->surfaces[i] = NULL;
10274562236bSHarry Wentland 			return false;
10284562236bSHarry Wentland 		}
10294562236bSHarry Wentland 
10304562236bSHarry Wentland 		free_pipe->surface = surface;
10314562236bSHarry Wentland 
10324562236bSHarry Wentland 		if (tail_pipe) {
10334562236bSHarry Wentland 			free_pipe->top_pipe = tail_pipe;
10344562236bSHarry Wentland 			tail_pipe->bottom_pipe = free_pipe;
10354562236bSHarry Wentland 		}
10364562236bSHarry Wentland 
10374562236bSHarry Wentland 		tail_pipe = free_pipe;
10384562236bSHarry Wentland 	}
10394562236bSHarry Wentland 
1040ab2541b6SAric Cyr 	release_free_pipes_for_stream(&context->res_ctx, dc_stream);
10414562236bSHarry Wentland 
10424562236bSHarry Wentland 	/* assign new surfaces*/
10434562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
1044ab2541b6SAric Cyr 		stream_status->surfaces[i] = surfaces[i];
10454562236bSHarry Wentland 
1046ab2541b6SAric Cyr 	stream_status->surface_count = surface_count;
10474562236bSHarry Wentland 
10484562236bSHarry Wentland 	return true;
10494562236bSHarry Wentland }
10504562236bSHarry Wentland 
10514562236bSHarry Wentland 
10524562236bSHarry Wentland static bool is_timing_changed(const struct core_stream *cur_stream,
10534562236bSHarry Wentland 		const struct core_stream *new_stream)
10544562236bSHarry Wentland {
10554562236bSHarry Wentland 	if (cur_stream == NULL)
10564562236bSHarry Wentland 		return true;
10574562236bSHarry Wentland 
10584562236bSHarry Wentland 	/* If sink pointer changed, it means this is a hotplug, we should do
10594562236bSHarry Wentland 	 * full hw setting.
10604562236bSHarry Wentland 	 */
10614562236bSHarry Wentland 	if (cur_stream->sink != new_stream->sink)
10624562236bSHarry Wentland 		return true;
10634562236bSHarry Wentland 
10644562236bSHarry Wentland 	/* If output color space is changed, need to reprogram info frames */
10654562236bSHarry Wentland 	if (cur_stream->public.output_color_space !=
10664562236bSHarry Wentland 			new_stream->public.output_color_space)
10674562236bSHarry Wentland 		return true;
10684562236bSHarry Wentland 
10694562236bSHarry Wentland 	return memcmp(
10704562236bSHarry Wentland 		&cur_stream->public.timing,
10714562236bSHarry Wentland 		&new_stream->public.timing,
10724562236bSHarry Wentland 		sizeof(struct dc_crtc_timing)) != 0;
10734562236bSHarry Wentland }
10744562236bSHarry Wentland 
10754562236bSHarry Wentland static bool are_stream_backends_same(
10764562236bSHarry Wentland 	const struct core_stream *stream_a, const struct core_stream *stream_b)
10774562236bSHarry Wentland {
10784562236bSHarry Wentland 	if (stream_a == stream_b)
10794562236bSHarry Wentland 		return true;
10804562236bSHarry Wentland 
10814562236bSHarry Wentland 	if (stream_a == NULL || stream_b == NULL)
10824562236bSHarry Wentland 		return false;
10834562236bSHarry Wentland 
10844562236bSHarry Wentland 	if (is_timing_changed(stream_a, stream_b))
10854562236bSHarry Wentland 		return false;
10864562236bSHarry Wentland 
10874562236bSHarry Wentland 	return true;
10884562236bSHarry Wentland }
10894562236bSHarry Wentland 
1090ab2541b6SAric Cyr bool is_stream_unchanged(
1091ab2541b6SAric Cyr 	const struct core_stream *old_stream, const struct core_stream *stream)
10924562236bSHarry Wentland {
10934562236bSHarry Wentland 
10944562236bSHarry Wentland 	if (!are_stream_backends_same(old_stream, stream))
10954562236bSHarry Wentland 		return false;
10964562236bSHarry Wentland 
10974562236bSHarry Wentland 	return true;
10984562236bSHarry Wentland }
10994562236bSHarry Wentland 
11004562236bSHarry Wentland bool resource_validate_attach_surfaces(
11014562236bSHarry Wentland 		const struct dc_validation_set set[],
11024562236bSHarry Wentland 		int set_count,
11034562236bSHarry Wentland 		const struct validate_context *old_context,
11044562236bSHarry Wentland 		struct validate_context *context)
11054562236bSHarry Wentland {
11064562236bSHarry Wentland 	int i, j;
11074562236bSHarry Wentland 
11084562236bSHarry Wentland 	for (i = 0; i < set_count; i++) {
1109ab2541b6SAric Cyr 		for (j = 0; j < old_context->stream_count; j++)
1110ab2541b6SAric Cyr 			if (is_stream_unchanged(
1111ab2541b6SAric Cyr 					old_context->streams[j],
1112ab2541b6SAric Cyr 					context->streams[i])) {
11134562236bSHarry Wentland 				if (!resource_attach_surfaces_to_context(
1114ab2541b6SAric Cyr 						old_context->stream_status[j].surfaces,
1115ab2541b6SAric Cyr 						old_context->stream_status[j].surface_count,
1116ab2541b6SAric Cyr 						&context->streams[i]->public,
11174562236bSHarry Wentland 						context))
11184562236bSHarry Wentland 					return false;
1119ab2541b6SAric Cyr 				context->stream_status[i] = old_context->stream_status[j];
11204562236bSHarry Wentland 			}
11214562236bSHarry Wentland 		if (set[i].surface_count != 0)
11224562236bSHarry Wentland 			if (!resource_attach_surfaces_to_context(
11234562236bSHarry Wentland 					set[i].surfaces,
11244562236bSHarry Wentland 					set[i].surface_count,
1125ab2541b6SAric Cyr 					&context->streams[i]->public,
11264562236bSHarry Wentland 					context))
11274562236bSHarry Wentland 				return false;
11284562236bSHarry Wentland 
11294562236bSHarry Wentland 	}
11304562236bSHarry Wentland 
11314562236bSHarry Wentland 	return true;
11324562236bSHarry Wentland }
11334562236bSHarry Wentland 
11344562236bSHarry Wentland /* Maximum TMDS single link pixel clock 165MHz */
11354562236bSHarry Wentland #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
11364562236bSHarry Wentland 
11374562236bSHarry Wentland static void set_stream_engine_in_use(
11384562236bSHarry Wentland 		struct resource_context *res_ctx,
11394562236bSHarry Wentland 		struct stream_encoder *stream_enc)
11404562236bSHarry Wentland {
11414562236bSHarry Wentland 	int i;
11424562236bSHarry Wentland 
11434562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
11444562236bSHarry Wentland 		if (res_ctx->pool->stream_enc[i] == stream_enc)
11454562236bSHarry Wentland 			res_ctx->is_stream_enc_acquired[i] = true;
11464562236bSHarry Wentland 	}
11474562236bSHarry Wentland }
11484562236bSHarry Wentland 
11494562236bSHarry Wentland /* TODO: release audio object */
11504562236bSHarry Wentland static void set_audio_in_use(
11514562236bSHarry Wentland 		struct resource_context *res_ctx,
11524562236bSHarry Wentland 		struct audio *audio)
11534562236bSHarry Wentland {
11544562236bSHarry Wentland 	int i;
11554562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->audio_count; i++) {
11564562236bSHarry Wentland 		if (res_ctx->pool->audios[i] == audio) {
11574562236bSHarry Wentland 			res_ctx->is_audio_acquired[i] = true;
11584562236bSHarry Wentland 		}
11594562236bSHarry Wentland 	}
11604562236bSHarry Wentland }
11614562236bSHarry Wentland 
11624562236bSHarry Wentland static int acquire_first_free_pipe(
11634562236bSHarry Wentland 		struct resource_context *res_ctx,
11644562236bSHarry Wentland 		struct core_stream *stream)
11654562236bSHarry Wentland {
11664562236bSHarry Wentland 	int i;
11674562236bSHarry Wentland 
11684562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->pipe_count; i++) {
11694562236bSHarry Wentland 		if (!res_ctx->pipe_ctx[i].stream) {
11704562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
11714562236bSHarry Wentland 
11724562236bSHarry Wentland 			pipe_ctx->tg = res_ctx->pool->timing_generators[i];
11734562236bSHarry Wentland 			pipe_ctx->mi = res_ctx->pool->mis[i];
11744562236bSHarry Wentland 			pipe_ctx->ipp = res_ctx->pool->ipps[i];
11754562236bSHarry Wentland 			pipe_ctx->xfm = res_ctx->pool->transforms[i];
11764562236bSHarry Wentland 			pipe_ctx->opp = res_ctx->pool->opps[i];
11774562236bSHarry Wentland 			pipe_ctx->dis_clk = res_ctx->pool->display_clock;
11784562236bSHarry Wentland 			pipe_ctx->pipe_idx = i;
11794562236bSHarry Wentland 
11804562236bSHarry Wentland 			pipe_ctx->stream = stream;
11814562236bSHarry Wentland 			return i;
11824562236bSHarry Wentland 		}
11834562236bSHarry Wentland 	}
11844562236bSHarry Wentland 	return -1;
11854562236bSHarry Wentland }
11864562236bSHarry Wentland 
11874562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link(
11884562236bSHarry Wentland 		struct resource_context *res_ctx,
11894562236bSHarry Wentland 		struct core_stream *stream)
11904562236bSHarry Wentland {
11914562236bSHarry Wentland 	int i;
11924562236bSHarry Wentland 	int j = -1;
11934562236bSHarry Wentland 	struct core_link *link = stream->sink->link;
11944562236bSHarry Wentland 
11954562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
11964562236bSHarry Wentland 		if (!res_ctx->is_stream_enc_acquired[i] &&
11974562236bSHarry Wentland 					res_ctx->pool->stream_enc[i]) {
11984562236bSHarry Wentland 			/* Store first available for MST second display
11994562236bSHarry Wentland 			 * in daisy chain use case */
12004562236bSHarry Wentland 			j = i;
12014562236bSHarry Wentland 			if (res_ctx->pool->stream_enc[i]->id ==
12024562236bSHarry Wentland 					link->link_enc->preferred_engine)
12034562236bSHarry Wentland 				return res_ctx->pool->stream_enc[i];
12044562236bSHarry Wentland 		}
12054562236bSHarry Wentland 	}
12064562236bSHarry Wentland 
12074562236bSHarry Wentland 	/*
12084562236bSHarry Wentland 	 * below can happen in cases when stream encoder is acquired:
12094562236bSHarry Wentland 	 * 1) for second MST display in chain, so preferred engine already
12104562236bSHarry Wentland 	 * acquired;
12114562236bSHarry Wentland 	 * 2) for another link, which preferred engine already acquired by any
12124562236bSHarry Wentland 	 * MST configuration.
12134562236bSHarry Wentland 	 *
12144562236bSHarry Wentland 	 * If signal is of DP type and preferred engine not found, return last available
12154562236bSHarry Wentland 	 *
12164562236bSHarry Wentland 	 * TODO - This is just a patch up and a generic solution is
12174562236bSHarry Wentland 	 * required for non DP connectors.
12184562236bSHarry Wentland 	 */
12194562236bSHarry Wentland 
12204562236bSHarry Wentland 	if (j >= 0 && dc_is_dp_signal(stream->signal))
12214562236bSHarry Wentland 		return res_ctx->pool->stream_enc[j];
12224562236bSHarry Wentland 
12234562236bSHarry Wentland 	return NULL;
12244562236bSHarry Wentland }
12254562236bSHarry Wentland 
12264562236bSHarry Wentland static struct audio *find_first_free_audio(struct resource_context *res_ctx)
12274562236bSHarry Wentland {
12284562236bSHarry Wentland 	int i;
12294562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->audio_count; i++) {
12304562236bSHarry Wentland 		if (res_ctx->is_audio_acquired[i] == false) {
12314562236bSHarry Wentland 			return res_ctx->pool->audios[i];
12324562236bSHarry Wentland 		}
12334562236bSHarry Wentland 	}
12344562236bSHarry Wentland 
12354562236bSHarry Wentland 	return 0;
12364562236bSHarry Wentland }
12374562236bSHarry Wentland 
12384562236bSHarry Wentland static void update_stream_signal(struct core_stream *stream)
12394562236bSHarry Wentland {
12404562236bSHarry Wentland 	const struct dc_sink *dc_sink = stream->public.sink;
12414562236bSHarry Wentland 
12422796eaeeSJoshua Aberback 	if (dc_sink->sink_signal == SIGNAL_TYPE_NONE)
12432796eaeeSJoshua Aberback 		stream->signal = stream->sink->link->public.connector_signal;
12442796eaeeSJoshua Aberback 	else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
12452796eaeeSJoshua Aberback 			dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK)
12464562236bSHarry Wentland 		/* For asic supports dual link DVI, we should adjust signal type
12474562236bSHarry Wentland 		 * based on timing pixel clock. If pixel clock more than 165Mhz,
12484562236bSHarry Wentland 		 * signal is dual link, otherwise, single link.
12494562236bSHarry Wentland 		 */
12502796eaeeSJoshua Aberback 		if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
12514562236bSHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
12524562236bSHarry Wentland 		else
12534562236bSHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
12542796eaeeSJoshua Aberback 	else
12552796eaeeSJoshua Aberback 		stream->signal = dc_sink->sink_signal;
12564562236bSHarry Wentland }
12574562236bSHarry Wentland 
12584562236bSHarry Wentland bool resource_is_stream_unchanged(
1259ab2541b6SAric Cyr 	const struct validate_context *old_context, const struct core_stream *stream)
12604562236bSHarry Wentland {
1261ab2541b6SAric Cyr 	int i;
12624562236bSHarry Wentland 
1263ab2541b6SAric Cyr 	for (i = 0; i < old_context->stream_count; i++) {
1264ab2541b6SAric Cyr 		const struct core_stream *old_stream = old_context->streams[i];
12654562236bSHarry Wentland 
12664562236bSHarry Wentland 		if (are_stream_backends_same(old_stream, stream))
12674562236bSHarry Wentland 				return true;
12684562236bSHarry Wentland 	}
12694562236bSHarry Wentland 
12704562236bSHarry Wentland 	return false;
12714562236bSHarry Wentland }
12724562236bSHarry Wentland 
12734562236bSHarry Wentland static void copy_pipe_ctx(
12744562236bSHarry Wentland 	const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
12754562236bSHarry Wentland {
12764562236bSHarry Wentland 	struct core_surface *surface = to_pipe_ctx->surface;
12774562236bSHarry Wentland 	struct core_stream *stream = to_pipe_ctx->stream;
12784562236bSHarry Wentland 
12794562236bSHarry Wentland 	*to_pipe_ctx = *from_pipe_ctx;
12804562236bSHarry Wentland 	to_pipe_ctx->stream = stream;
12814562236bSHarry Wentland 	if (surface != NULL)
12824562236bSHarry Wentland 		to_pipe_ctx->surface = surface;
12834562236bSHarry Wentland }
12844562236bSHarry Wentland 
12854562236bSHarry Wentland static struct core_stream *find_pll_sharable_stream(
12864562236bSHarry Wentland 		const struct core_stream *stream_needs_pll,
12874562236bSHarry Wentland 		struct validate_context *context)
12884562236bSHarry Wentland {
1289ab2541b6SAric Cyr 	int i;
12904562236bSHarry Wentland 
1291ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1292ab2541b6SAric Cyr 		struct core_stream *stream_has_pll = context->streams[i];
12934562236bSHarry Wentland 
12944562236bSHarry Wentland 		/* We are looking for non dp, non virtual stream */
12954562236bSHarry Wentland 		if (resource_are_streams_timing_synchronizable(
12964562236bSHarry Wentland 			stream_needs_pll, stream_has_pll)
12974562236bSHarry Wentland 			&& !dc_is_dp_signal(stream_has_pll->signal)
12984562236bSHarry Wentland 			&& stream_has_pll->sink->link->public.connector_signal
12994562236bSHarry Wentland 			!= SIGNAL_TYPE_VIRTUAL)
13004562236bSHarry Wentland 			return stream_has_pll;
1301ab2541b6SAric Cyr 
13024562236bSHarry Wentland 	}
13034562236bSHarry Wentland 
13044562236bSHarry Wentland 	return NULL;
13054562236bSHarry Wentland }
13064562236bSHarry Wentland 
13074562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
13084562236bSHarry Wentland {
13094562236bSHarry Wentland 	uint32_t pix_clk = timing->pix_clk_khz;
13104562236bSHarry Wentland 	uint32_t normalized_pix_clk = pix_clk;
13114562236bSHarry Wentland 
13124562236bSHarry Wentland 	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
13134562236bSHarry Wentland 		pix_clk /= 2;
1314cc4d99b8SCharlene Liu 	if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
13154562236bSHarry Wentland 		switch (timing->display_color_depth) {
13164562236bSHarry Wentland 		case COLOR_DEPTH_888:
13174562236bSHarry Wentland 			normalized_pix_clk = pix_clk;
13184562236bSHarry Wentland 			break;
13194562236bSHarry Wentland 		case COLOR_DEPTH_101010:
13204562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 30) / 24;
13214562236bSHarry Wentland 			break;
13224562236bSHarry Wentland 		case COLOR_DEPTH_121212:
13234562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 36) / 24;
13244562236bSHarry Wentland 		break;
13254562236bSHarry Wentland 		case COLOR_DEPTH_161616:
13264562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 48) / 24;
13274562236bSHarry Wentland 		break;
13284562236bSHarry Wentland 		default:
13294562236bSHarry Wentland 			ASSERT(0);
13304562236bSHarry Wentland 		break;
13314562236bSHarry Wentland 		}
1332cc4d99b8SCharlene Liu 	}
13334562236bSHarry Wentland 	return normalized_pix_clk;
13344562236bSHarry Wentland }
13354562236bSHarry Wentland 
13364562236bSHarry Wentland static void calculate_phy_pix_clks(
13374562236bSHarry Wentland 		const struct core_dc *dc,
13384562236bSHarry Wentland 		struct validate_context *context)
13394562236bSHarry Wentland {
1340ab2541b6SAric Cyr 	int i;
13414562236bSHarry Wentland 
1342ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1343ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
13444562236bSHarry Wentland 
13454562236bSHarry Wentland 		update_stream_signal(stream);
13464562236bSHarry Wentland 
13474562236bSHarry Wentland 		/* update actual pixel clock on all streams */
13484562236bSHarry Wentland 		if (dc_is_hdmi_signal(stream->signal))
13494562236bSHarry Wentland 			stream->phy_pix_clk = get_norm_pix_clk(
13504562236bSHarry Wentland 				&stream->public.timing);
13514562236bSHarry Wentland 		else
13524562236bSHarry Wentland 			stream->phy_pix_clk =
13534562236bSHarry Wentland 				stream->public.timing.pix_clk_khz;
13544562236bSHarry Wentland 	}
13554562236bSHarry Wentland }
13564562236bSHarry Wentland 
13574562236bSHarry Wentland enum dc_status resource_map_pool_resources(
13584562236bSHarry Wentland 		const struct core_dc *dc,
13594562236bSHarry Wentland 		struct validate_context *context)
13604562236bSHarry Wentland {
1361ab2541b6SAric Cyr 	int i, j;
13624562236bSHarry Wentland 
13634562236bSHarry Wentland 	calculate_phy_pix_clks(dc, context);
13644562236bSHarry Wentland 
1365ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1366ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
13674562236bSHarry Wentland 
13684b679bc3SCharlene Liu 		if (!resource_is_stream_unchanged(dc->current_context, stream)) {
13694b679bc3SCharlene Liu 			if (stream != NULL && dc->current_context->streams[i] != NULL) {
13704b679bc3SCharlene Liu 				stream->bit_depth_params =
13714b679bc3SCharlene Liu 						dc->current_context->streams[i]->bit_depth_params;
13724b679bc3SCharlene Liu 				stream->clamping = dc->current_context->streams[i]->clamping;
13734562236bSHarry Wentland 			continue;
13744b679bc3SCharlene Liu 		}
13754b679bc3SCharlene Liu 	}
13767e2fe319SCharlene Liu 
13774562236bSHarry Wentland 		/* mark resources used for stream that is already active */
1378ab2541b6SAric Cyr 		for (j = 0; j < MAX_PIPES; j++) {
13794562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx =
1380ab2541b6SAric Cyr 				&context->res_ctx.pipe_ctx[j];
13814562236bSHarry Wentland 			const struct pipe_ctx *old_pipe_ctx =
1382ab2541b6SAric Cyr 				&dc->current_context->res_ctx.pipe_ctx[j];
13834562236bSHarry Wentland 
13844562236bSHarry Wentland 			if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
13854562236bSHarry Wentland 				continue;
13864562236bSHarry Wentland 
1387268cadbdSYongqiang Sun 			if (old_pipe_ctx->top_pipe)
1388268cadbdSYongqiang Sun 				continue;
1389268cadbdSYongqiang Sun 
13904562236bSHarry Wentland 			pipe_ctx->stream = stream;
13914562236bSHarry Wentland 			copy_pipe_ctx(old_pipe_ctx, pipe_ctx);
13924562236bSHarry Wentland 
13938c737fccSYongqiang Sun 			/* Split pipe resource, do not acquire back end */
13948c737fccSYongqiang Sun 			if (!pipe_ctx->stream_enc)
13958c737fccSYongqiang Sun 				continue;
13968c737fccSYongqiang Sun 
13974562236bSHarry Wentland 			set_stream_engine_in_use(
13984562236bSHarry Wentland 				&context->res_ctx,
13994562236bSHarry Wentland 				pipe_ctx->stream_enc);
14004562236bSHarry Wentland 
14014562236bSHarry Wentland 			/* Switch to dp clock source only if there is
14024562236bSHarry Wentland 			 * no non dp stream that shares the same timing
14034562236bSHarry Wentland 			 * with the dp stream.
14044562236bSHarry Wentland 			 */
14054562236bSHarry Wentland 			if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
14064562236bSHarry Wentland 				!find_pll_sharable_stream(stream, context))
14074562236bSHarry Wentland 				pipe_ctx->clock_source =
14084562236bSHarry Wentland 					context->res_ctx.pool->dp_clock_source;
14094562236bSHarry Wentland 
14104562236bSHarry Wentland 			resource_reference_clock_source(
14114562236bSHarry Wentland 				&context->res_ctx,
14124562236bSHarry Wentland 				pipe_ctx->clock_source);
14134562236bSHarry Wentland 
14144562236bSHarry Wentland 			set_audio_in_use(&context->res_ctx,
14154562236bSHarry Wentland 					 pipe_ctx->audio);
14164562236bSHarry Wentland 		}
14174562236bSHarry Wentland 	}
14184562236bSHarry Wentland 
1419ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1420ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
14214562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx = NULL;
14224562236bSHarry Wentland 		int pipe_idx = -1;
14234562236bSHarry Wentland 
14244562236bSHarry Wentland 		if (resource_is_stream_unchanged(dc->current_context, stream))
14254562236bSHarry Wentland 			continue;
14264562236bSHarry Wentland 		/* acquire new resources */
1427ab2541b6SAric Cyr 		pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream);
14284562236bSHarry Wentland 		if (pipe_idx < 0)
14294562236bSHarry Wentland 			return DC_NO_CONTROLLER_RESOURCE;
14304562236bSHarry Wentland 
14314562236bSHarry Wentland 
14324562236bSHarry Wentland 		pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
14334562236bSHarry Wentland 
14344562236bSHarry Wentland 		pipe_ctx->stream_enc =
14354562236bSHarry Wentland 			find_first_free_match_stream_enc_for_link(
14364562236bSHarry Wentland 				&context->res_ctx, stream);
14374562236bSHarry Wentland 
14384562236bSHarry Wentland 		if (!pipe_ctx->stream_enc)
14394562236bSHarry Wentland 			return DC_NO_STREAM_ENG_RESOURCE;
14404562236bSHarry Wentland 
14414562236bSHarry Wentland 		set_stream_engine_in_use(
14424562236bSHarry Wentland 			&context->res_ctx,
14434562236bSHarry Wentland 			pipe_ctx->stream_enc);
14444562236bSHarry Wentland 
14454562236bSHarry Wentland 		/* TODO: Add check if ASIC support and EDID audio */
14464a9a5d62SZeyu Fan 		if (!stream->sink->public.converter_disable_audio &&
14474562236bSHarry Wentland 			dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
14484562236bSHarry Wentland 			stream->public.audio_info.mode_count) {
14494562236bSHarry Wentland 			pipe_ctx->audio = find_first_free_audio(
14504562236bSHarry Wentland 				&context->res_ctx);
14514562236bSHarry Wentland 
14524562236bSHarry Wentland 			/*
14534562236bSHarry Wentland 			 * Audio assigned in order first come first get.
14544562236bSHarry Wentland 			 * There are asics which has number of audio
14554562236bSHarry Wentland 			 * resources less then number of pipes
14564562236bSHarry Wentland 			 */
14574562236bSHarry Wentland 			if (pipe_ctx->audio)
14584562236bSHarry Wentland 				set_audio_in_use(
14594562236bSHarry Wentland 					&context->res_ctx,
14604562236bSHarry Wentland 					pipe_ctx->audio);
14614562236bSHarry Wentland 		}
14624562236bSHarry Wentland 
1463ab2541b6SAric Cyr 		context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst;
14644562236bSHarry Wentland 	}
14654562236bSHarry Wentland 
14664562236bSHarry Wentland 	return DC_OK;
14674562236bSHarry Wentland }
14684562236bSHarry Wentland 
1469ab2541b6SAric Cyr /* first stream in the context is used to populate the rest */
1470ab2541b6SAric Cyr void validate_guaranteed_copy_streams(
14714562236bSHarry Wentland 		struct validate_context *context,
1472ab2541b6SAric Cyr 		int max_streams)
14734562236bSHarry Wentland {
14744562236bSHarry Wentland 	int i;
14754562236bSHarry Wentland 
1476ab2541b6SAric Cyr 	for (i = 1; i < max_streams; i++) {
1477ab2541b6SAric Cyr 		context->streams[i] = context->streams[0];
14784562236bSHarry Wentland 
14794562236bSHarry Wentland 		copy_pipe_ctx(&context->res_ctx.pipe_ctx[0],
14804562236bSHarry Wentland 			      &context->res_ctx.pipe_ctx[i]);
14814562236bSHarry Wentland 		context->res_ctx.pipe_ctx[i].stream =
14824562236bSHarry Wentland 				context->res_ctx.pipe_ctx[0].stream;
14834562236bSHarry Wentland 
1484ab2541b6SAric Cyr 		dc_stream_retain(&context->streams[i]->public);
1485ab2541b6SAric Cyr 		context->stream_count++;
14864562236bSHarry Wentland 	}
14874562236bSHarry Wentland }
14884562236bSHarry Wentland 
14896e4d6beeSTony Cheng static void patch_gamut_packet_checksum(
14906e4d6beeSTony Cheng 		struct encoder_info_packet *gamut_packet)
14914562236bSHarry Wentland {
14924562236bSHarry Wentland 	/* For gamut we recalc checksum */
14936e4d6beeSTony Cheng 	if (gamut_packet->valid) {
14944562236bSHarry Wentland 		uint8_t chk_sum = 0;
14954562236bSHarry Wentland 		uint8_t *ptr;
14964562236bSHarry Wentland 		uint8_t i;
14974562236bSHarry Wentland 
14984562236bSHarry Wentland 		/*start of the Gamut data. */
14996e4d6beeSTony Cheng 		ptr = &gamut_packet->sb[3];
15004562236bSHarry Wentland 
15016e4d6beeSTony Cheng 		for (i = 0; i <= gamut_packet->sb[1]; i++)
15024562236bSHarry Wentland 			chk_sum += ptr[i];
15034562236bSHarry Wentland 
15046e4d6beeSTony Cheng 		gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
15051646a6feSAndrew Wong 	}
15064562236bSHarry Wentland }
15074562236bSHarry Wentland 
15084562236bSHarry Wentland static void set_avi_info_frame(
15096e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
15104562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
15114562236bSHarry Wentland {
15124562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
15134562236bSHarry Wentland 	enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
15144562236bSHarry Wentland 	struct info_frame info_frame = { {0} };
15154562236bSHarry Wentland 	uint32_t pixel_encoding = 0;
15164562236bSHarry Wentland 	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
15174562236bSHarry Wentland 	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
15184562236bSHarry Wentland 	bool itc = false;
15194562236bSHarry Wentland 	uint8_t cn0_cn1 = 0;
15204562236bSHarry Wentland 	uint8_t *check_sum = NULL;
15214562236bSHarry Wentland 	uint8_t byte_index = 0;
15224562236bSHarry Wentland 
15234562236bSHarry Wentland 	color_space = pipe_ctx->stream->public.output_color_space;
15244562236bSHarry Wentland 
15254562236bSHarry Wentland 	/* Initialize header */
15264562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.
15273e183c5fSDave Airlie 			info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
15284562236bSHarry Wentland 	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
15294562236bSHarry Wentland 	* not be used in HDMI 2.0 (Section 10.1) */
15303e183c5fSDave Airlie 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2;
15314562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.length =
15323e183c5fSDave Airlie 			HDMI_AVI_INFOFRAME_SIZE;
15334562236bSHarry Wentland 
15344562236bSHarry Wentland 	/*
15354562236bSHarry Wentland 	 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
15364562236bSHarry Wentland 	 * according to HDMI 2.0 spec (Section 10.1)
15374562236bSHarry Wentland 	 */
15384562236bSHarry Wentland 
15394562236bSHarry Wentland 	switch (stream->public.timing.pixel_encoding) {
15404562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR422:
15414562236bSHarry Wentland 		pixel_encoding = 1;
15424562236bSHarry Wentland 		break;
15434562236bSHarry Wentland 
15444562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR444:
15454562236bSHarry Wentland 		pixel_encoding = 2;
15464562236bSHarry Wentland 		break;
15474562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR420:
15484562236bSHarry Wentland 		pixel_encoding = 3;
15494562236bSHarry Wentland 		break;
15504562236bSHarry Wentland 
15514562236bSHarry Wentland 	case PIXEL_ENCODING_RGB:
15524562236bSHarry Wentland 	default:
15534562236bSHarry Wentland 		pixel_encoding = 0;
15544562236bSHarry Wentland 	}
15554562236bSHarry Wentland 
15564562236bSHarry Wentland 	/* Y0_Y1_Y2 : The pixel encoding */
15574562236bSHarry Wentland 	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
15584562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 =
15594562236bSHarry Wentland 		pixel_encoding;
15604562236bSHarry Wentland 
15614562236bSHarry Wentland 	/* A0 = 1 Active Format Information valid */
15624562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.A0 =
15634562236bSHarry Wentland 		ACTIVE_FORMAT_VALID;
15644562236bSHarry Wentland 
15654562236bSHarry Wentland 	/* B0, B1 = 3; Bar info data is valid */
15664562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 =
15674562236bSHarry Wentland 		BAR_INFO_BOTH_VALID;
15684562236bSHarry Wentland 
15694562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 =
15704562236bSHarry Wentland 			PICTURE_SCALING_UNIFORM;
15714562236bSHarry Wentland 
15724562236bSHarry Wentland 	/* S0, S1 : Underscan / Overscan */
15734562236bSHarry Wentland 	/* TODO: un-hardcode scan type */
15744562236bSHarry Wentland 	scan_type = SCANNING_TYPE_UNDERSCAN;
15754562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type;
15764562236bSHarry Wentland 
15774562236bSHarry Wentland 	/* C0, C1 : Colorimetry */
15788fde5884SCharlene Liu 	if (color_space == COLOR_SPACE_YCBCR709 ||
15798fde5884SCharlene Liu 			color_space == COLOR_SPACE_YCBCR709_LIMITED)
15804562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
15814562236bSHarry Wentland 				COLORIMETRY_ITU709;
15828fde5884SCharlene Liu 	else if (color_space == COLOR_SPACE_YCBCR601 ||
15838fde5884SCharlene Liu 			color_space == COLOR_SPACE_YCBCR601_LIMITED)
15844562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
15854562236bSHarry Wentland 				COLORIMETRY_ITU601;
15868fde5884SCharlene Liu 	else {
15878fde5884SCharlene Liu 		if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB)
15888fde5884SCharlene Liu 			BREAK_TO_DEBUGGER();
15894562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
15904562236bSHarry Wentland 				COLORIMETRY_NO_DATA;
15918fde5884SCharlene Liu 	}
1592534db198SAmy Zhang 	if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
1593534db198SAmy Zhang 			color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
1594534db198SAmy Zhang 			color_space == COLOR_SPACE_2020_YCBCR) {
1595534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
1596534db198SAmy Zhang 				COLORIMETRYEX_BT2020RGBYCBCR;
1597534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1598534db198SAmy Zhang 				COLORIMETRY_EXTENDED;
1599534db198SAmy Zhang 	} else if (color_space == COLOR_SPACE_ADOBERGB) {
1600534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
1601534db198SAmy Zhang 				COLORIMETRYEX_ADOBERGB;
1602534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1603534db198SAmy Zhang 				COLORIMETRY_EXTENDED;
1604534db198SAmy Zhang 	}
1605534db198SAmy Zhang 
16064562236bSHarry Wentland 	/* TODO: un-hardcode aspect ratio */
16074562236bSHarry Wentland 	aspect = stream->public.timing.aspect_ratio;
16084562236bSHarry Wentland 
16094562236bSHarry Wentland 	switch (aspect) {
16104562236bSHarry Wentland 	case ASPECT_RATIO_4_3:
16114562236bSHarry Wentland 	case ASPECT_RATIO_16_9:
16124562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect;
16134562236bSHarry Wentland 		break;
16144562236bSHarry Wentland 
16154562236bSHarry Wentland 	case ASPECT_RATIO_NO_DATA:
16164562236bSHarry Wentland 	case ASPECT_RATIO_64_27:
16174562236bSHarry Wentland 	case ASPECT_RATIO_256_135:
16184562236bSHarry Wentland 	default:
16194562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0;
16204562236bSHarry Wentland 	}
16214562236bSHarry Wentland 
16224562236bSHarry Wentland 	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
16234562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 =
16244562236bSHarry Wentland 			ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
16254562236bSHarry Wentland 
16264562236bSHarry Wentland 	/* TODO: un-hardcode cn0_cn1 and itc */
16274562236bSHarry Wentland 	cn0_cn1 = 0;
16284562236bSHarry Wentland 	itc = false;
16294562236bSHarry Wentland 
16304562236bSHarry Wentland 	if (itc) {
16314562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1;
16324562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 =
16334562236bSHarry Wentland 			cn0_cn1;
16344562236bSHarry Wentland 	}
16354562236bSHarry Wentland 
16364562236bSHarry Wentland 	/* TODO : We should handle YCC quantization */
16374562236bSHarry Wentland 	/* but we do not have matrix calculation */
16384562236bSHarry Wentland 	if (color_space == COLOR_SPACE_SRGB) {
16394562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
16404562236bSHarry Wentland 						RGB_QUANTIZATION_FULL_RANGE;
16414562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
16424562236bSHarry Wentland 						YYC_QUANTIZATION_FULL_RANGE;
16434562236bSHarry Wentland 	} else if (color_space == COLOR_SPACE_SRGB_LIMITED) {
16444562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
16454562236bSHarry Wentland 						RGB_QUANTIZATION_LIMITED_RANGE;
16464562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
16474562236bSHarry Wentland 						YYC_QUANTIZATION_LIMITED_RANGE;
16484562236bSHarry Wentland 	} else {
16494562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
16504562236bSHarry Wentland 						RGB_QUANTIZATION_DEFAULT_RANGE;
16514562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
16524562236bSHarry Wentland 						YYC_QUANTIZATION_LIMITED_RANGE;
16534562236bSHarry Wentland 	}
16544562236bSHarry Wentland 
16554562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 =
16564562236bSHarry Wentland 					stream->public.timing.vic;
16574562236bSHarry Wentland 
16584562236bSHarry Wentland 	/* pixel repetition
16594562236bSHarry Wentland 	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
16604562236bSHarry Wentland 	 * repetition start from 1 */
16614562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0;
16624562236bSHarry Wentland 
16634562236bSHarry Wentland 	/* Bar Info
16644562236bSHarry Wentland 	 * barTop:    Line Number of End of Top Bar.
16654562236bSHarry Wentland 	 * barBottom: Line Number of Start of Bottom Bar.
16664562236bSHarry Wentland 	 * barLeft:   Pixel Number of End of Left Bar.
16674562236bSHarry Wentland 	 * barRight:  Pixel Number of Start of Right Bar. */
16684562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top =
16694562236bSHarry Wentland 			stream->public.timing.v_border_top;
16704562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom =
16714562236bSHarry Wentland 		(stream->public.timing.v_border_top
16724562236bSHarry Wentland 			- stream->public.timing.v_border_bottom + 1);
16734562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left =
16744562236bSHarry Wentland 			stream->public.timing.h_border_left;
16754562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right =
16764562236bSHarry Wentland 		(stream->public.timing.h_total
16774562236bSHarry Wentland 			- stream->public.timing.h_border_right + 1);
16784562236bSHarry Wentland 
16794562236bSHarry Wentland 	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
16804562236bSHarry Wentland 	check_sum =
16814562236bSHarry Wentland 		&info_frame.
16824562236bSHarry Wentland 		avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
16833e183c5fSDave Airlie 	*check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2;
16844562236bSHarry Wentland 
16853e183c5fSDave Airlie 	for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++)
16864562236bSHarry Wentland 		*check_sum += info_frame.avi_info_packet.info_packet_hdmi.
16874562236bSHarry Wentland 				packet_raw_data.sb[byte_index];
16884562236bSHarry Wentland 
16894562236bSHarry Wentland 	/* one byte complement */
16904562236bSHarry Wentland 	*check_sum = (uint8_t) (0x100 - *check_sum);
16914562236bSHarry Wentland 
16924562236bSHarry Wentland 	/* Store in hw_path_mode */
16934562236bSHarry Wentland 	info_packet->hb0 =
16944562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0;
16954562236bSHarry Wentland 	info_packet->hb1 =
16964562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1;
16974562236bSHarry Wentland 	info_packet->hb2 =
16984562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2;
16994562236bSHarry Wentland 
1700e66e4d64SHarry Wentland 	for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet.
1701e66e4d64SHarry Wentland 				info_packet_hdmi.packet_raw_data.sb); byte_index++)
17024562236bSHarry Wentland 		info_packet->sb[byte_index] = info_frame.avi_info_packet.
17034562236bSHarry Wentland 				info_packet_hdmi.packet_raw_data.sb[byte_index];
17044562236bSHarry Wentland 
17054562236bSHarry Wentland 	info_packet->valid = true;
17064562236bSHarry Wentland }
17074562236bSHarry Wentland 
17086e4d6beeSTony Cheng static void set_vendor_info_packet(
17096e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
17106e4d6beeSTony Cheng 		struct core_stream *stream)
17114562236bSHarry Wentland {
17124562236bSHarry Wentland 	uint32_t length = 0;
17134562236bSHarry Wentland 	bool hdmi_vic_mode = false;
17144562236bSHarry Wentland 	uint8_t checksum = 0;
17154562236bSHarry Wentland 	uint32_t i = 0;
17164562236bSHarry Wentland 	enum dc_timing_3d_format format;
17174562236bSHarry Wentland 
17184562236bSHarry Wentland 	format = stream->public.timing.timing_3d_format;
17194562236bSHarry Wentland 
17204562236bSHarry Wentland 	/* Can be different depending on packet content */
17214562236bSHarry Wentland 	length = 5;
17224562236bSHarry Wentland 
17234562236bSHarry Wentland 	if (stream->public.timing.hdmi_vic != 0
17244562236bSHarry Wentland 			&& stream->public.timing.h_total >= 3840
17254562236bSHarry Wentland 			&& stream->public.timing.v_total >= 2160)
17264562236bSHarry Wentland 		hdmi_vic_mode = true;
17274562236bSHarry Wentland 
17284562236bSHarry Wentland 	/* According to HDMI 1.4a CTS, VSIF should be sent
17294562236bSHarry Wentland 	 * for both 3D stereo and HDMI VIC modes.
17304562236bSHarry Wentland 	 * For all other modes, there is no VSIF sent.  */
17314562236bSHarry Wentland 
17324562236bSHarry Wentland 	if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
17334562236bSHarry Wentland 		return;
17344562236bSHarry Wentland 
17354562236bSHarry Wentland 	/* 24bit IEEE Registration identifier (0x000c03). LSB first. */
17364562236bSHarry Wentland 	info_packet->sb[1] = 0x03;
17374562236bSHarry Wentland 	info_packet->sb[2] = 0x0C;
17384562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
17394562236bSHarry Wentland 
17404562236bSHarry Wentland 	/*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
17414562236bSHarry Wentland 	 * The value for HDMI_Video_Format are:
17424562236bSHarry Wentland 	 * 0x0 (0b000) - No additional HDMI video format is presented in this
17434562236bSHarry Wentland 	 * packet
17444562236bSHarry Wentland 	 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
17454562236bSHarry Wentland 	 * parameter follows
17464562236bSHarry Wentland 	 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
17474562236bSHarry Wentland 	 * potentially 3D_Ext_Data follows
17484562236bSHarry Wentland 	 * 0x3..0x7 (0b011..0b111) - reserved for future use */
17494562236bSHarry Wentland 	if (format != TIMING_3D_FORMAT_NONE)
17504562236bSHarry Wentland 		info_packet->sb[4] = (2 << 5);
17514562236bSHarry Wentland 	else if (hdmi_vic_mode)
17524562236bSHarry Wentland 		info_packet->sb[4] = (1 << 5);
17534562236bSHarry Wentland 
17544562236bSHarry Wentland 	/* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
17554562236bSHarry Wentland 	 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
17564562236bSHarry Wentland 	 * The value for 3D_Structure are:
17574562236bSHarry Wentland 	 * 0x0 - Frame Packing
17584562236bSHarry Wentland 	 * 0x1 - Field Alternative
17594562236bSHarry Wentland 	 * 0x2 - Line Alternative
17604562236bSHarry Wentland 	 * 0x3 - Side-by-Side (full)
17614562236bSHarry Wentland 	 * 0x4 - L + depth
17624562236bSHarry Wentland 	 * 0x5 - L + depth + graphics + graphics-depth
17634562236bSHarry Wentland 	 * 0x6 - Top-and-Bottom
17644562236bSHarry Wentland 	 * 0x7 - Reserved for future use
17654562236bSHarry Wentland 	 * 0x8 - Side-by-Side (Half)
17664562236bSHarry Wentland 	 * 0x9..0xE - Reserved for future use
17674562236bSHarry Wentland 	 * 0xF - Not used */
17684562236bSHarry Wentland 	switch (format) {
17694562236bSHarry Wentland 	case TIMING_3D_FORMAT_HW_FRAME_PACKING:
17704562236bSHarry Wentland 	case TIMING_3D_FORMAT_SW_FRAME_PACKING:
17714562236bSHarry Wentland 		info_packet->sb[5] = (0x0 << 4);
17724562236bSHarry Wentland 		break;
17734562236bSHarry Wentland 
17744562236bSHarry Wentland 	case TIMING_3D_FORMAT_SIDE_BY_SIDE:
17754562236bSHarry Wentland 	case TIMING_3D_FORMAT_SBS_SW_PACKED:
17764562236bSHarry Wentland 		info_packet->sb[5] = (0x8 << 4);
17774562236bSHarry Wentland 		length = 6;
17784562236bSHarry Wentland 		break;
17794562236bSHarry Wentland 
17804562236bSHarry Wentland 	case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
17814562236bSHarry Wentland 	case TIMING_3D_FORMAT_TB_SW_PACKED:
17824562236bSHarry Wentland 		info_packet->sb[5] = (0x6 << 4);
17834562236bSHarry Wentland 		break;
17844562236bSHarry Wentland 
17854562236bSHarry Wentland 	default:
17864562236bSHarry Wentland 		break;
17874562236bSHarry Wentland 	}
17884562236bSHarry Wentland 
17894562236bSHarry Wentland 	/*PB5: If PB4 is set to 0x1 (extended resolution format)
17904562236bSHarry Wentland 	 * fill PB5 with the correct HDMI VIC code */
17914562236bSHarry Wentland 	if (hdmi_vic_mode)
17924562236bSHarry Wentland 		info_packet->sb[5] = stream->public.timing.hdmi_vic;
17934562236bSHarry Wentland 
17944562236bSHarry Wentland 	/* Header */
17953e183c5fSDave Airlie 	info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */
17964562236bSHarry Wentland 	info_packet->hb1 = 0x01; /* Version */
17974562236bSHarry Wentland 
17984562236bSHarry Wentland 	/* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
17994562236bSHarry Wentland 	info_packet->hb2 = (uint8_t) (length);
18004562236bSHarry Wentland 
18014562236bSHarry Wentland 	/* Calculate checksum */
18024562236bSHarry Wentland 	checksum = 0;
18034562236bSHarry Wentland 	checksum += info_packet->hb0;
18044562236bSHarry Wentland 	checksum += info_packet->hb1;
18054562236bSHarry Wentland 	checksum += info_packet->hb2;
18064562236bSHarry Wentland 
18074562236bSHarry Wentland 	for (i = 1; i <= length; i++)
18084562236bSHarry Wentland 		checksum += info_packet->sb[i];
18094562236bSHarry Wentland 
18104562236bSHarry Wentland 	info_packet->sb[0] = (uint8_t) (0x100 - checksum);
18114562236bSHarry Wentland 
18124562236bSHarry Wentland 	info_packet->valid = true;
18134562236bSHarry Wentland }
18144562236bSHarry Wentland 
18156e4d6beeSTony Cheng static void set_spd_info_packet(
18166e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
18176e4d6beeSTony Cheng 		struct core_stream *stream)
18184562236bSHarry Wentland {
18194562236bSHarry Wentland 	/* SPD info packet for FreeSync */
18204562236bSHarry Wentland 
18214562236bSHarry Wentland 	unsigned char checksum = 0;
18224562236bSHarry Wentland 	unsigned int idx, payload_size = 0;
18234562236bSHarry Wentland 
18244562236bSHarry Wentland 	/* Check if Freesync is supported. Return if false. If true,
18254562236bSHarry Wentland 	 * set the corresponding bit in the info packet
18264562236bSHarry Wentland 	 */
18274562236bSHarry Wentland 	if (stream->public.freesync_ctx.supported == false)
18284562236bSHarry Wentland 		return;
18294562236bSHarry Wentland 
18304562236bSHarry Wentland 	if (dc_is_hdmi_signal(stream->signal)) {
18314562236bSHarry Wentland 
18324562236bSHarry Wentland 		/* HEADER */
18334562236bSHarry Wentland 
18344562236bSHarry Wentland 		/* HB0  = Packet Type = 0x83 (Source Product
18354562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
18364562236bSHarry Wentland 		 */
18373e183c5fSDave Airlie 		info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD;
18384562236bSHarry Wentland 
18394562236bSHarry Wentland 		/* HB1  = Version = 0x01 */
18404562236bSHarry Wentland 		info_packet->hb1 = 0x01;
18414562236bSHarry Wentland 
18424562236bSHarry Wentland 		/* HB2  = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
18434562236bSHarry Wentland 		info_packet->hb2 = 0x08;
18444562236bSHarry Wentland 
18454562236bSHarry Wentland 		payload_size = 0x08;
18464562236bSHarry Wentland 
18474562236bSHarry Wentland 	} else if (dc_is_dp_signal(stream->signal)) {
18484562236bSHarry Wentland 
18494562236bSHarry Wentland 		/* HEADER */
18504562236bSHarry Wentland 
18514562236bSHarry Wentland 		/* HB0  = Secondary-data Packet ID = 0 - Only non-zero
18524562236bSHarry Wentland 		 *	  when used to associate audio related info packets
18534562236bSHarry Wentland 		 */
18544562236bSHarry Wentland 		info_packet->hb0 = 0x00;
18554562236bSHarry Wentland 
18564562236bSHarry Wentland 		/* HB1  = Packet Type = 0x83 (Source Product
18574562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
18584562236bSHarry Wentland 		 */
18593e183c5fSDave Airlie 		info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD;
18604562236bSHarry Wentland 
18614562236bSHarry Wentland 		/* HB2  = [Bits 7:0 = Least significant eight bits -
18624562236bSHarry Wentland 		 *	  For INFOFRAME, the value must be 1Bh]
18634562236bSHarry Wentland 		 */
18644562236bSHarry Wentland 		info_packet->hb2 = 0x1B;
18654562236bSHarry Wentland 
18664562236bSHarry Wentland 		/* HB3  = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
18674562236bSHarry Wentland 		 *	  [Bits 1:0 = Most significant two bits = 0x00]
18684562236bSHarry Wentland 		 */
18694562236bSHarry Wentland 		info_packet->hb3 = 0x04;
18704562236bSHarry Wentland 
18714562236bSHarry Wentland 		payload_size = 0x1B;
18724562236bSHarry Wentland 	}
18734562236bSHarry Wentland 
18744562236bSHarry Wentland 	/* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
18754562236bSHarry Wentland 	info_packet->sb[1] = 0x1A;
18764562236bSHarry Wentland 
18774562236bSHarry Wentland 	/* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
18784562236bSHarry Wentland 	info_packet->sb[2] = 0x00;
18794562236bSHarry Wentland 
18804562236bSHarry Wentland 	/* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
18814562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
18824562236bSHarry Wentland 
18834562236bSHarry Wentland 	/* PB4 = Reserved */
18844562236bSHarry Wentland 	info_packet->sb[4] = 0x00;
18854562236bSHarry Wentland 
18864562236bSHarry Wentland 	/* PB5 = Reserved */
18874562236bSHarry Wentland 	info_packet->sb[5] = 0x00;
18884562236bSHarry Wentland 
18894562236bSHarry Wentland 	/* PB6 = [Bits 7:3 = Reserved] */
18904562236bSHarry Wentland 	info_packet->sb[6] = 0x00;
18914562236bSHarry Wentland 
18924562236bSHarry Wentland 	if (stream->public.freesync_ctx.supported == true)
18934562236bSHarry Wentland 		/* PB6 = [Bit 0 = FreeSync Supported] */
18944562236bSHarry Wentland 		info_packet->sb[6] |= 0x01;
18954562236bSHarry Wentland 
18964562236bSHarry Wentland 	if (stream->public.freesync_ctx.enabled == true)
18974562236bSHarry Wentland 		/* PB6 = [Bit 1 = FreeSync Enabled] */
18984562236bSHarry Wentland 		info_packet->sb[6] |= 0x02;
18994562236bSHarry Wentland 
19004562236bSHarry Wentland 	if (stream->public.freesync_ctx.active == true)
19014562236bSHarry Wentland 		/* PB6 = [Bit 2 = FreeSync Active] */
19024562236bSHarry Wentland 		info_packet->sb[6] |= 0x04;
19034562236bSHarry Wentland 
19044562236bSHarry Wentland 	/* PB7 = FreeSync Minimum refresh rate (Hz) */
19054562236bSHarry Wentland 	info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx.
19064562236bSHarry Wentland 			min_refresh_in_micro_hz / 1000000);
19074562236bSHarry Wentland 
19084562236bSHarry Wentland 	/* PB8 = FreeSync Maximum refresh rate (Hz)
19094562236bSHarry Wentland 	 *
19104562236bSHarry Wentland 	 * Note: We do not use the maximum capable refresh rate
19114562236bSHarry Wentland 	 * of the panel, because we should never go above the field
19124562236bSHarry Wentland 	 * rate of the mode timing set.
19134562236bSHarry Wentland 	 */
19144562236bSHarry Wentland 	info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx.
19154562236bSHarry Wentland 			nominal_refresh_in_micro_hz / 1000000);
19164562236bSHarry Wentland 
19174562236bSHarry Wentland 	/* PB9 - PB27  = Reserved */
19184562236bSHarry Wentland 	for (idx = 9; idx <= 27; idx++)
19194562236bSHarry Wentland 		info_packet->sb[idx] = 0x00;
19204562236bSHarry Wentland 
19214562236bSHarry Wentland 	/* Calculate checksum */
19224562236bSHarry Wentland 	checksum += info_packet->hb0;
19234562236bSHarry Wentland 	checksum += info_packet->hb1;
19244562236bSHarry Wentland 	checksum += info_packet->hb2;
19254562236bSHarry Wentland 	checksum += info_packet->hb3;
19264562236bSHarry Wentland 
19274562236bSHarry Wentland 	for (idx = 1; idx <= payload_size; idx++)
19284562236bSHarry Wentland 		checksum += info_packet->sb[idx];
19294562236bSHarry Wentland 
19304562236bSHarry Wentland 	/* PB0 = Checksum (one byte complement) */
19314562236bSHarry Wentland 	info_packet->sb[0] = (unsigned char) (0x100 - checksum);
19324562236bSHarry Wentland 
19334562236bSHarry Wentland 	info_packet->valid = true;
19344562236bSHarry Wentland }
19354562236bSHarry Wentland 
19361646a6feSAndrew Wong static void set_hdr_static_info_packet(
19376e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
19381646a6feSAndrew Wong 		struct core_surface *surface,
19396e4d6beeSTony Cheng 		struct core_stream *stream)
19401646a6feSAndrew Wong {
1941e5cf325bSHarry Wentland 	uint16_t i = 0;
19421646a6feSAndrew Wong 	enum signal_type signal = stream->signal;
1943e5cf325bSHarry Wentland 	struct dc_hdr_static_metadata hdr_metadata;
1944e5cf325bSHarry Wentland 	uint32_t data;
19451646a6feSAndrew Wong 
19461646a6feSAndrew Wong 	if (!surface)
19471646a6feSAndrew Wong 		return;
19481646a6feSAndrew Wong 
1949e5cf325bSHarry Wentland 	hdr_metadata = surface->public.hdr_static_ctx;
19501646a6feSAndrew Wong 
195170063a59SAmy Zhang 	if (!hdr_metadata.hdr_supported)
195210bff005SYongqiang Sun 		return;
195310bff005SYongqiang Sun 
19541646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
19551646a6feSAndrew Wong 		info_packet->valid = true;
19561646a6feSAndrew Wong 
19571646a6feSAndrew Wong 		info_packet->hb0 = 0x87;
19581646a6feSAndrew Wong 		info_packet->hb1 = 0x01;
19591646a6feSAndrew Wong 		info_packet->hb2 = 0x1A;
19601646a6feSAndrew Wong 		i = 1;
19611646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
19621646a6feSAndrew Wong 		info_packet->valid = true;
19631646a6feSAndrew Wong 
19641646a6feSAndrew Wong 		info_packet->hb0 = 0x00;
19651646a6feSAndrew Wong 		info_packet->hb1 = 0x87;
19661646a6feSAndrew Wong 		info_packet->hb2 = 0x1D;
19671646a6feSAndrew Wong 		info_packet->hb3 = (0x13 << 2);
19681646a6feSAndrew Wong 		i = 2;
19691646a6feSAndrew Wong 	}
19701646a6feSAndrew Wong 
19711646a6feSAndrew Wong 	data = hdr_metadata.is_hdr;
19721646a6feSAndrew Wong 	info_packet->sb[i++] = data ? 0x02 : 0x00;
19731646a6feSAndrew Wong 	info_packet->sb[i++] = 0x00;
19741646a6feSAndrew Wong 
19751646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_x / 2;
19761646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
19771646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
19781646a6feSAndrew Wong 
19791646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_y / 2;
19801646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
19811646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
19821646a6feSAndrew Wong 
19831646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_x / 2;
19841646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
19851646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
19861646a6feSAndrew Wong 
19871646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_y / 2;
19881646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
19891646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
19901646a6feSAndrew Wong 
19911646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_x / 2;
19921646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
19931646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
19941646a6feSAndrew Wong 
19951646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_y / 2;
19961646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
19971646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
19981646a6feSAndrew Wong 
19991646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_x / 2;
20001646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
20011646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
20021646a6feSAndrew Wong 
20031646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_y / 2;
20041646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
20051646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
20061646a6feSAndrew Wong 
20071646a6feSAndrew Wong 	data = hdr_metadata.max_luminance;
20081646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
20091646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
20101646a6feSAndrew Wong 
20111646a6feSAndrew Wong 	data = hdr_metadata.min_luminance;
20121646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
20131646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
20141646a6feSAndrew Wong 
20151646a6feSAndrew Wong 	data = hdr_metadata.maximum_content_light_level;
20161646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
20171646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
20181646a6feSAndrew Wong 
20191646a6feSAndrew Wong 	data = hdr_metadata.maximum_frame_average_light_level;
20201646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
20211646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
20221646a6feSAndrew Wong 
20231646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
20241646a6feSAndrew Wong 		uint32_t checksum = 0;
20251646a6feSAndrew Wong 
20261646a6feSAndrew Wong 		checksum += info_packet->hb0;
20271646a6feSAndrew Wong 		checksum += info_packet->hb1;
20281646a6feSAndrew Wong 		checksum += info_packet->hb2;
20291646a6feSAndrew Wong 
20301646a6feSAndrew Wong 		for (i = 1; i <= info_packet->hb2; i++)
20311646a6feSAndrew Wong 			checksum += info_packet->sb[i];
20321646a6feSAndrew Wong 
20331646a6feSAndrew Wong 		info_packet->sb[0] = 0x100 - checksum;
20341646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
20351646a6feSAndrew Wong 		info_packet->sb[0] = 0x01;
20361646a6feSAndrew Wong 		info_packet->sb[1] = 0x1A;
20371646a6feSAndrew Wong 	}
20381646a6feSAndrew Wong }
20391646a6feSAndrew Wong 
20406e4d6beeSTony Cheng static void set_vsc_info_packet(
20416e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
20426e4d6beeSTony Cheng 		struct core_stream *stream)
20434562236bSHarry Wentland {
20444562236bSHarry Wentland 	unsigned int vscPacketRevision = 0;
20454562236bSHarry Wentland 	unsigned int i;
20464562236bSHarry Wentland 
20474562236bSHarry Wentland 	if (stream->sink->link->public.psr_caps.psr_version != 0) {
20484562236bSHarry Wentland 		vscPacketRevision = 2;
20494562236bSHarry Wentland 	}
20504562236bSHarry Wentland 
20514562236bSHarry Wentland 	/* VSC packet not needed based on the features
20524562236bSHarry Wentland 	 * supported by this DP display
20534562236bSHarry Wentland 	 */
20544562236bSHarry Wentland 	if (vscPacketRevision == 0)
20554562236bSHarry Wentland 		return;
20564562236bSHarry Wentland 
20574562236bSHarry Wentland 	if (vscPacketRevision == 0x2) {
20584562236bSHarry Wentland 		/* Secondary-data Packet ID = 0*/
20594562236bSHarry Wentland 		info_packet->hb0 = 0x00;
20604562236bSHarry Wentland 		/* 07h - Packet Type Value indicating Video
20614562236bSHarry Wentland 		 * Stream Configuration packet
20624562236bSHarry Wentland 		 */
20634562236bSHarry Wentland 		info_packet->hb1 = 0x07;
20644562236bSHarry Wentland 		/* 02h = VSC SDP supporting 3D stereo and PSR
20654562236bSHarry Wentland 		 * (applies to eDP v1.3 or higher).
20664562236bSHarry Wentland 		 */
20674562236bSHarry Wentland 		info_packet->hb2 = 0x02;
20684562236bSHarry Wentland 		/* 08h = VSC packet supporting 3D stereo + PSR
20694562236bSHarry Wentland 		 * (HB2 = 02h).
20704562236bSHarry Wentland 		 */
20714562236bSHarry Wentland 		info_packet->hb3 = 0x08;
20724562236bSHarry Wentland 
20734562236bSHarry Wentland 		for (i = 0; i < 28; i++)
20744562236bSHarry Wentland 			info_packet->sb[i] = 0;
20754562236bSHarry Wentland 
20764562236bSHarry Wentland 		info_packet->valid = true;
20774562236bSHarry Wentland 	}
20784562236bSHarry Wentland 
20794562236bSHarry Wentland 	/*TODO: stereo 3D support and extend pixel encoding colorimetry*/
20804562236bSHarry Wentland }
20814562236bSHarry Wentland 
20824562236bSHarry Wentland void resource_validate_ctx_destruct(struct validate_context *context)
20834562236bSHarry Wentland {
20844562236bSHarry Wentland 	int i, j;
20854562236bSHarry Wentland 
2086ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
2087ab2541b6SAric Cyr 		for (j = 0; j < context->stream_status[i].surface_count; j++)
20884562236bSHarry Wentland 			dc_surface_release(
2089ab2541b6SAric Cyr 				context->stream_status[i].surfaces[j]);
20904562236bSHarry Wentland 
2091ab2541b6SAric Cyr 		context->stream_status[i].surface_count = 0;
2092ab2541b6SAric Cyr 		dc_stream_release(&context->streams[i]->public);
2093ab2541b6SAric Cyr 		context->streams[i] = NULL;
20944562236bSHarry Wentland 	}
20954562236bSHarry Wentland }
20964562236bSHarry Wentland 
20974562236bSHarry Wentland /*
2098ab2541b6SAric Cyr  * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced
20994562236bSHarry Wentland  * by the src_ctx
21004562236bSHarry Wentland  */
21014562236bSHarry Wentland void resource_validate_ctx_copy_construct(
21024562236bSHarry Wentland 		const struct validate_context *src_ctx,
21034562236bSHarry Wentland 		struct validate_context *dst_ctx)
21044562236bSHarry Wentland {
21054562236bSHarry Wentland 	int i, j;
21064562236bSHarry Wentland 
21074562236bSHarry Wentland 	*dst_ctx = *src_ctx;
21084562236bSHarry Wentland 
21094562236bSHarry Wentland 	for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) {
21104562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
21114562236bSHarry Wentland 
21124562236bSHarry Wentland 		if (cur_pipe->top_pipe)
21134562236bSHarry Wentland 			cur_pipe->top_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
21144562236bSHarry Wentland 
21154562236bSHarry Wentland 		if (cur_pipe->bottom_pipe)
21164562236bSHarry Wentland 			cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
21174562236bSHarry Wentland 
21184562236bSHarry Wentland 	}
21194562236bSHarry Wentland 
2120ab2541b6SAric Cyr 	for (i = 0; i < dst_ctx->stream_count; i++) {
2121ab2541b6SAric Cyr 		dc_stream_retain(&dst_ctx->streams[i]->public);
2122ab2541b6SAric Cyr 		for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++)
21234562236bSHarry Wentland 			dc_surface_retain(
2124ab2541b6SAric Cyr 				dst_ctx->stream_status[i].surfaces[j]);
21254562236bSHarry Wentland 	}
21264562236bSHarry Wentland }
21274562236bSHarry Wentland 
21284562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll(
21294562236bSHarry Wentland 		struct resource_context *res_ctx)
21304562236bSHarry Wentland {
21314562236bSHarry Wentland 	int i;
21324562236bSHarry Wentland 
21334562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; ++i) {
21344562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
21354562236bSHarry Wentland 			return res_ctx->pool->clock_sources[i];
21364562236bSHarry Wentland 	}
21374562236bSHarry Wentland 
21384562236bSHarry Wentland 	return NULL;
21394562236bSHarry Wentland }
21404562236bSHarry Wentland 
21414562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
21424562236bSHarry Wentland {
21434562236bSHarry Wentland 	enum signal_type signal = SIGNAL_TYPE_NONE;
21446e4d6beeSTony Cheng 	struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame;
21454562236bSHarry Wentland 
21464562236bSHarry Wentland 	/* default all packets to invalid */
21476e4d6beeSTony Cheng 	info->avi.valid = false;
21486e4d6beeSTony Cheng 	info->gamut.valid = false;
21496e4d6beeSTony Cheng 	info->vendor.valid = false;
21506e4d6beeSTony Cheng 	info->hdrsmd.valid = false;
21516e4d6beeSTony Cheng 	info->vsc.valid = false;
21524562236bSHarry Wentland 
21534562236bSHarry Wentland 	signal = pipe_ctx->stream->signal;
21544562236bSHarry Wentland 
21554562236bSHarry Wentland 	/* HDMi and DP have different info packets*/
21564562236bSHarry Wentland 	if (dc_is_hdmi_signal(signal)) {
21576e4d6beeSTony Cheng 		set_avi_info_frame(&info->avi, pipe_ctx);
21586e4d6beeSTony Cheng 
21596e4d6beeSTony Cheng 		set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
21606e4d6beeSTony Cheng 
21616e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
21626e4d6beeSTony Cheng 
21636e4d6beeSTony Cheng 		set_hdr_static_info_packet(&info->hdrsmd,
21646e4d6beeSTony Cheng 				pipe_ctx->surface, pipe_ctx->stream);
21656e4d6beeSTony Cheng 
2166a33fa99dSHarry Wentland 	} else if (dc_is_dp_signal(signal)) {
21676e4d6beeSTony Cheng 		set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
21686e4d6beeSTony Cheng 
21696e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
21706e4d6beeSTony Cheng 
21716e4d6beeSTony Cheng 		set_hdr_static_info_packet(&info->hdrsmd,
21726e4d6beeSTony Cheng 				pipe_ctx->surface, pipe_ctx->stream);
2173a33fa99dSHarry Wentland 	}
21744562236bSHarry Wentland 
21756e4d6beeSTony Cheng 	patch_gamut_packet_checksum(&info->gamut);
21764562236bSHarry Wentland }
21774562236bSHarry Wentland 
21784562236bSHarry Wentland enum dc_status resource_map_clock_resources(
21794562236bSHarry Wentland 		const struct core_dc *dc,
21804562236bSHarry Wentland 		struct validate_context *context)
21814562236bSHarry Wentland {
2182ab2541b6SAric Cyr 	int i, j;
21834562236bSHarry Wentland 
21844562236bSHarry Wentland 	/* acquire new resources */
2185ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
2186ab2541b6SAric Cyr 		const struct core_stream *stream = context->streams[i];
21874562236bSHarry Wentland 
21884562236bSHarry Wentland 		if (resource_is_stream_unchanged(dc->current_context, stream))
21894562236bSHarry Wentland 			continue;
21904562236bSHarry Wentland 
2191ab2541b6SAric Cyr 		for (j = 0; j < MAX_PIPES; j++) {
21924562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx =
2193ab2541b6SAric Cyr 				&context->res_ctx.pipe_ctx[j];
21944562236bSHarry Wentland 
2195ab2541b6SAric Cyr 			if (context->res_ctx.pipe_ctx[j].stream != stream)
21964562236bSHarry Wentland 				continue;
21974562236bSHarry Wentland 
21984562236bSHarry Wentland 			if (dc_is_dp_signal(pipe_ctx->stream->signal)
21994562236bSHarry Wentland 				|| pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
22004562236bSHarry Wentland 				pipe_ctx->clock_source =
22014562236bSHarry Wentland 					context->res_ctx.pool->dp_clock_source;
22024562236bSHarry Wentland 			else {
22034562236bSHarry Wentland 				pipe_ctx->clock_source = NULL;
22044562236bSHarry Wentland 
22054562236bSHarry Wentland 				if (!dc->public.config.disable_disp_pll_sharing)
22064562236bSHarry Wentland 					resource_find_used_clk_src_for_sharing(
22074562236bSHarry Wentland 						&context->res_ctx,
22084562236bSHarry Wentland 						pipe_ctx);
22094562236bSHarry Wentland 
22104562236bSHarry Wentland 				if (pipe_ctx->clock_source == NULL)
22114562236bSHarry Wentland 					pipe_ctx->clock_source =
22124562236bSHarry Wentland 						dc_resource_find_first_free_pll(&context->res_ctx);
22134562236bSHarry Wentland 			}
22144562236bSHarry Wentland 
22154562236bSHarry Wentland 			if (pipe_ctx->clock_source == NULL)
22164562236bSHarry Wentland 				return DC_NO_CLOCK_SOURCE_RESOURCE;
22174562236bSHarry Wentland 
22184562236bSHarry Wentland 			resource_reference_clock_source(
22194562236bSHarry Wentland 				&context->res_ctx,
22204562236bSHarry Wentland 				pipe_ctx->clock_source);
22214562236bSHarry Wentland 
22224562236bSHarry Wentland 			/* only one cs per stream regardless of mpo */
22234562236bSHarry Wentland 			break;
22244562236bSHarry Wentland 		}
22254562236bSHarry Wentland 	}
22264562236bSHarry Wentland 
22274562236bSHarry Wentland 	return DC_OK;
22284562236bSHarry Wentland }
22294562236bSHarry Wentland 
22304562236bSHarry Wentland /*
22314562236bSHarry Wentland  * Note: We need to disable output if clock sources change,
22324562236bSHarry Wentland  * since bios does optimization and doesn't apply if changing
22334562236bSHarry Wentland  * PHY when not already disabled.
22344562236bSHarry Wentland  */
22354562236bSHarry Wentland bool pipe_need_reprogram(
22364562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx_old,
22374562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
22384562236bSHarry Wentland {
22394562236bSHarry Wentland 	if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
22404562236bSHarry Wentland 		return true;
22414562236bSHarry Wentland 
22424562236bSHarry Wentland 	if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
22434562236bSHarry Wentland 		return true;
22444562236bSHarry Wentland 
22454562236bSHarry Wentland 	if (pipe_ctx_old->audio != pipe_ctx->audio)
22464562236bSHarry Wentland 		return true;
22474562236bSHarry Wentland 
22484562236bSHarry Wentland 	if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
22494562236bSHarry Wentland 			&& pipe_ctx_old->stream != pipe_ctx->stream)
22504562236bSHarry Wentland 		return true;
22514562236bSHarry Wentland 
22524562236bSHarry Wentland 	if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc)
22534562236bSHarry Wentland 		return true;
22544562236bSHarry Wentland 
22554562236bSHarry Wentland 	if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
22564562236bSHarry Wentland 		return true;
22574562236bSHarry Wentland 
22584562236bSHarry Wentland 
22594562236bSHarry Wentland 	return false;
22604562236bSHarry Wentland }
2261