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"
424562236bSHarry Wentland 
434562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
444562236bSHarry Wentland {
454562236bSHarry Wentland 	enum dce_version dc_version = DCE_VERSION_UNKNOWN;
464562236bSHarry Wentland 	switch (asic_id.chip_family) {
474562236bSHarry Wentland 
484562236bSHarry Wentland 	case FAMILY_CI:
494562236bSHarry Wentland 	case FAMILY_KV:
504562236bSHarry Wentland 		dc_version = DCE_VERSION_8_0;
514562236bSHarry Wentland 		break;
524562236bSHarry Wentland 	case FAMILY_CZ:
534562236bSHarry Wentland 		dc_version = DCE_VERSION_11_0;
544562236bSHarry Wentland 		break;
554562236bSHarry Wentland 
564562236bSHarry Wentland 	case FAMILY_VI:
574562236bSHarry Wentland 		if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
584562236bSHarry Wentland 				ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
594562236bSHarry Wentland 			dc_version = DCE_VERSION_10_0;
604562236bSHarry Wentland 			break;
614562236bSHarry Wentland 		}
624562236bSHarry Wentland 		if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
63b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
64b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
654562236bSHarry Wentland 			dc_version = DCE_VERSION_11_2;
664562236bSHarry Wentland 		}
674562236bSHarry Wentland 		break;
684562236bSHarry Wentland 	default:
694562236bSHarry Wentland 		dc_version = DCE_VERSION_UNKNOWN;
704562236bSHarry Wentland 		break;
714562236bSHarry Wentland 	}
724562236bSHarry Wentland 	return dc_version;
734562236bSHarry Wentland }
744562236bSHarry Wentland 
754562236bSHarry Wentland struct resource_pool *dc_create_resource_pool(
764562236bSHarry Wentland 				struct core_dc *dc,
774562236bSHarry Wentland 				int num_virtual_links,
784562236bSHarry Wentland 				enum dce_version dc_version,
794562236bSHarry Wentland 				struct hw_asic_id asic_id)
804562236bSHarry Wentland {
815ac3d3c9SCharlene Liu 	struct resource_pool *res_pool = NULL;
824562236bSHarry Wentland 
834562236bSHarry Wentland 	switch (dc_version) {
844562236bSHarry Wentland 	case DCE_VERSION_8_0:
855ac3d3c9SCharlene Liu 		res_pool = dce80_create_resource_pool(
864562236bSHarry Wentland 			num_virtual_links, dc);
875ac3d3c9SCharlene Liu 		break;
884562236bSHarry Wentland 	case DCE_VERSION_10_0:
895ac3d3c9SCharlene Liu 		res_pool = dce100_create_resource_pool(
904562236bSHarry Wentland 				num_virtual_links, dc);
915ac3d3c9SCharlene Liu 		break;
924562236bSHarry Wentland 	case DCE_VERSION_11_0:
935ac3d3c9SCharlene Liu 		res_pool = dce110_create_resource_pool(
944562236bSHarry Wentland 			num_virtual_links, dc, asic_id);
955ac3d3c9SCharlene Liu 		break;
964562236bSHarry Wentland 	case DCE_VERSION_11_2:
975ac3d3c9SCharlene Liu 		res_pool = dce112_create_resource_pool(
984562236bSHarry Wentland 			num_virtual_links, dc);
995ac3d3c9SCharlene Liu 		break;
1004562236bSHarry Wentland 	default:
1014562236bSHarry Wentland 		break;
1024562236bSHarry Wentland 	}
1035ac3d3c9SCharlene Liu 	if (res_pool != NULL) {
1045ac3d3c9SCharlene Liu 		struct firmware_info fw_info = { { 0 } };
1054562236bSHarry Wentland 
1065ac3d3c9SCharlene Liu 		if (dc->ctx->dc_bios->funcs->get_firmware_info(
1075ac3d3c9SCharlene Liu 				dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) {
1085ac3d3c9SCharlene Liu 				res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency;
1095ac3d3c9SCharlene Liu 			} else
1105ac3d3c9SCharlene Liu 				ASSERT_CRITICAL(false);
1115ac3d3c9SCharlene Liu 	}
1125ac3d3c9SCharlene Liu 
1135ac3d3c9SCharlene Liu 	return res_pool;
1144562236bSHarry Wentland }
1154562236bSHarry Wentland 
1164562236bSHarry Wentland void dc_destroy_resource_pool(struct core_dc *dc)
1174562236bSHarry Wentland {
1184562236bSHarry Wentland 	if (dc) {
1194562236bSHarry Wentland 		if (dc->res_pool)
1204562236bSHarry Wentland 			dc->res_pool->funcs->destroy(&dc->res_pool);
1214562236bSHarry Wentland 
1224562236bSHarry Wentland 		if (dc->hwseq)
1234562236bSHarry Wentland 			dm_free(dc->hwseq);
1244562236bSHarry Wentland 	}
1254562236bSHarry Wentland }
1264562236bSHarry Wentland 
1274562236bSHarry Wentland static void update_num_audio(
1284562236bSHarry Wentland 	const struct resource_straps *straps,
1294562236bSHarry Wentland 	unsigned int *num_audio,
1304562236bSHarry Wentland 	struct audio_support *aud_support)
1314562236bSHarry Wentland {
1324562236bSHarry Wentland 	if (straps->hdmi_disable == 0) {
1334562236bSHarry Wentland 		aud_support->hdmi_audio_native = true;
1344562236bSHarry Wentland 		aud_support->hdmi_audio_on_dongle = true;
1354562236bSHarry Wentland 		aud_support->dp_audio = true;
1364562236bSHarry Wentland 	} else {
1374562236bSHarry Wentland 		if (straps->dc_pinstraps_audio & 0x2) {
1384562236bSHarry Wentland 			aud_support->hdmi_audio_on_dongle = true;
1394562236bSHarry Wentland 			aud_support->dp_audio = true;
1404562236bSHarry Wentland 		} else {
1414562236bSHarry Wentland 			aud_support->dp_audio = true;
1424562236bSHarry Wentland 		}
1434562236bSHarry Wentland 	}
1444562236bSHarry Wentland 
1454562236bSHarry Wentland 	switch (straps->audio_stream_number) {
1464562236bSHarry Wentland 	case 0: /* multi streams supported */
1474562236bSHarry Wentland 		break;
1484562236bSHarry Wentland 	case 1: /* multi streams not supported */
1494562236bSHarry Wentland 		*num_audio = 1;
1504562236bSHarry Wentland 		break;
1514562236bSHarry Wentland 	default:
1524562236bSHarry Wentland 		DC_ERR("DC: unexpected audio fuse!\n");
15317a96033SJulia Lawall 	}
1544562236bSHarry Wentland }
1554562236bSHarry Wentland 
1564562236bSHarry Wentland bool resource_construct(
1574562236bSHarry Wentland 	unsigned int num_virtual_links,
1584562236bSHarry Wentland 	struct core_dc *dc,
1594562236bSHarry Wentland 	struct resource_pool *pool,
1604562236bSHarry Wentland 	const struct resource_create_funcs *create_funcs)
1614562236bSHarry Wentland {
1624562236bSHarry Wentland 	struct dc_context *ctx = dc->ctx;
1634562236bSHarry Wentland 	const struct resource_caps *caps = pool->res_cap;
1644562236bSHarry Wentland 	int i;
1654562236bSHarry Wentland 	unsigned int num_audio = caps->num_audio;
1664562236bSHarry Wentland 	struct resource_straps straps = {0};
1674562236bSHarry Wentland 
1684562236bSHarry Wentland 	if (create_funcs->read_dce_straps)
1694562236bSHarry Wentland 		create_funcs->read_dce_straps(dc->ctx, &straps);
1704562236bSHarry Wentland 
1714562236bSHarry Wentland 	pool->audio_count = 0;
1724562236bSHarry Wentland 	if (create_funcs->create_audio) {
1734562236bSHarry Wentland 		/* find the total number of streams available via the
1744562236bSHarry Wentland 		 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
1754562236bSHarry Wentland 		 * registers (one for each pin) starting from pin 1
1764562236bSHarry Wentland 		 * up to the max number of audio pins.
1774562236bSHarry Wentland 		 * We stop on the first pin where
1784562236bSHarry Wentland 		 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
1794562236bSHarry Wentland 		 */
1804562236bSHarry Wentland 		update_num_audio(&straps, &num_audio, &pool->audio_support);
1814562236bSHarry Wentland 		for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
1824562236bSHarry Wentland 			struct audio *aud = create_funcs->create_audio(ctx, i);
1834562236bSHarry Wentland 
1844562236bSHarry Wentland 			if (aud == NULL) {
1854562236bSHarry Wentland 				DC_ERR("DC: failed to create audio!\n");
1864562236bSHarry Wentland 				return false;
1874562236bSHarry Wentland 			}
1884562236bSHarry Wentland 
1894562236bSHarry Wentland 			if (!aud->funcs->endpoint_valid(aud)) {
1904562236bSHarry Wentland 				aud->funcs->destroy(&aud);
1914562236bSHarry Wentland 				break;
1924562236bSHarry Wentland 			}
1934562236bSHarry Wentland 
1944562236bSHarry Wentland 			pool->audios[i] = aud;
1954562236bSHarry Wentland 			pool->audio_count++;
1964562236bSHarry Wentland 		}
1974562236bSHarry Wentland 	}
1984562236bSHarry Wentland 
1994562236bSHarry Wentland 	pool->stream_enc_count = 0;
2004562236bSHarry Wentland 	if (create_funcs->create_stream_encoder) {
2014562236bSHarry Wentland 		for (i = 0; i < caps->num_stream_encoder; i++) {
2024562236bSHarry Wentland 			pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
2034562236bSHarry Wentland 			if (pool->stream_enc[i] == NULL)
2044562236bSHarry Wentland 				DC_ERR("DC: failed to create stream_encoder!\n");
2054562236bSHarry Wentland 			pool->stream_enc_count++;
2064562236bSHarry Wentland 		}
2074562236bSHarry Wentland 	}
2084562236bSHarry Wentland 
2094562236bSHarry Wentland 	for (i = 0; i < num_virtual_links; i++) {
2104562236bSHarry Wentland 		pool->stream_enc[pool->stream_enc_count] =
2114562236bSHarry Wentland 			virtual_stream_encoder_create(
2124562236bSHarry Wentland 					ctx, ctx->dc_bios);
2134562236bSHarry Wentland 		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
2144562236bSHarry Wentland 			DC_ERR("DC: failed to create stream_encoder!\n");
2154562236bSHarry Wentland 			return false;
2164562236bSHarry Wentland 		}
2174562236bSHarry Wentland 		pool->stream_enc_count++;
2184562236bSHarry Wentland 	}
2194562236bSHarry Wentland 
2204562236bSHarry Wentland 	dc->hwseq = create_funcs->create_hwseq(ctx);
2214562236bSHarry Wentland 
2224562236bSHarry Wentland 	return true;
2234562236bSHarry Wentland }
2244562236bSHarry Wentland 
2254562236bSHarry Wentland 
2264562236bSHarry Wentland void resource_unreference_clock_source(
2274562236bSHarry Wentland 		struct resource_context *res_ctx,
2288c737fccSYongqiang Sun 		struct clock_source **clock_source)
2294562236bSHarry Wentland {
2304562236bSHarry Wentland 	int i;
2314562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; i++) {
2328c737fccSYongqiang Sun 		if (res_ctx->pool->clock_sources[i] != *clock_source)
2334562236bSHarry Wentland 			continue;
2344562236bSHarry Wentland 
2354562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]--;
2364562236bSHarry Wentland 
2374562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
2388c737fccSYongqiang Sun 			(*clock_source)->funcs->cs_power_down(*clock_source);
2394562236bSHarry Wentland 
2404562236bSHarry Wentland 		break;
2414562236bSHarry Wentland 	}
2424562236bSHarry Wentland 
2438c737fccSYongqiang Sun 	if (res_ctx->pool->dp_clock_source == *clock_source) {
2444562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count--;
2454562236bSHarry Wentland 
2464562236bSHarry Wentland 		if (res_ctx->dp_clock_source_ref_count == 0)
2478c737fccSYongqiang Sun 			(*clock_source)->funcs->cs_power_down(*clock_source);
2484562236bSHarry Wentland 	}
2498c737fccSYongqiang Sun 	*clock_source = NULL;
2504562236bSHarry Wentland }
2514562236bSHarry Wentland 
2524562236bSHarry Wentland void resource_reference_clock_source(
2534562236bSHarry Wentland 		struct resource_context *res_ctx,
2544562236bSHarry Wentland 		struct clock_source *clock_source)
2554562236bSHarry Wentland {
2564562236bSHarry Wentland 	int i;
2574562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; i++) {
2584562236bSHarry Wentland 		if (res_ctx->pool->clock_sources[i] != clock_source)
2594562236bSHarry Wentland 			continue;
2604562236bSHarry Wentland 
2614562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]++;
2624562236bSHarry Wentland 		break;
2634562236bSHarry Wentland 	}
2644562236bSHarry Wentland 
2654562236bSHarry Wentland 	if (res_ctx->pool->dp_clock_source == clock_source)
2664562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count++;
2674562236bSHarry Wentland }
2684562236bSHarry Wentland 
2694562236bSHarry Wentland bool resource_are_streams_timing_synchronizable(
2704562236bSHarry Wentland 	const struct core_stream *stream1,
2714562236bSHarry Wentland 	const struct core_stream *stream2)
2724562236bSHarry Wentland {
2734562236bSHarry Wentland 	if (stream1->public.timing.h_total != stream2->public.timing.h_total)
2744562236bSHarry Wentland 		return false;
2754562236bSHarry Wentland 
2764562236bSHarry Wentland 	if (stream1->public.timing.v_total != stream2->public.timing.v_total)
2774562236bSHarry Wentland 		return false;
2784562236bSHarry Wentland 
2794562236bSHarry Wentland 	if (stream1->public.timing.h_addressable
2804562236bSHarry Wentland 				!= stream2->public.timing.h_addressable)
2814562236bSHarry Wentland 		return false;
2824562236bSHarry Wentland 
2834562236bSHarry Wentland 	if (stream1->public.timing.v_addressable
2844562236bSHarry Wentland 				!= stream2->public.timing.v_addressable)
2854562236bSHarry Wentland 		return false;
2864562236bSHarry Wentland 
2874562236bSHarry Wentland 	if (stream1->public.timing.pix_clk_khz
2884562236bSHarry Wentland 				!= stream2->public.timing.pix_clk_khz)
2894562236bSHarry Wentland 		return false;
2904562236bSHarry Wentland 
2914562236bSHarry Wentland 	if (stream1->phy_pix_clk != stream2->phy_pix_clk
2924562236bSHarry Wentland 			&& !dc_is_dp_signal(stream1->signal)
2934562236bSHarry Wentland 			&& !dc_is_dp_signal(stream2->signal))
2944562236bSHarry Wentland 		return false;
2954562236bSHarry Wentland 
2964562236bSHarry Wentland 	return true;
2974562236bSHarry Wentland }
2984562236bSHarry Wentland 
2994562236bSHarry Wentland static bool is_sharable_clk_src(
3004562236bSHarry Wentland 	const struct pipe_ctx *pipe_with_clk_src,
3014562236bSHarry Wentland 	const struct pipe_ctx *pipe)
3024562236bSHarry Wentland {
3034562236bSHarry Wentland 	if (pipe_with_clk_src->clock_source == NULL)
3044562236bSHarry Wentland 		return false;
3054562236bSHarry Wentland 
3064562236bSHarry Wentland 	if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
3074562236bSHarry Wentland 		return false;
3084562236bSHarry Wentland 
3094562236bSHarry Wentland 	if (dc_is_dp_signal(pipe_with_clk_src->stream->signal))
3104562236bSHarry Wentland 		return false;
3114562236bSHarry Wentland 
3124562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
3134562236bSHarry Wentland 			&& dc_is_dvi_signal(pipe->stream->signal))
3144562236bSHarry Wentland 		return false;
3154562236bSHarry Wentland 
3164562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe->stream->signal)
3174562236bSHarry Wentland 			&& dc_is_dvi_signal(pipe_with_clk_src->stream->signal))
3184562236bSHarry Wentland 		return false;
3194562236bSHarry Wentland 
3204562236bSHarry Wentland 	if (!resource_are_streams_timing_synchronizable(
3214562236bSHarry Wentland 			pipe_with_clk_src->stream, pipe->stream))
3224562236bSHarry Wentland 		return false;
3234562236bSHarry Wentland 
3244562236bSHarry Wentland 	return true;
3254562236bSHarry Wentland }
3264562236bSHarry Wentland 
3274562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing(
3284562236bSHarry Wentland 					struct resource_context *res_ctx,
3294562236bSHarry Wentland 					struct pipe_ctx *pipe_ctx)
3304562236bSHarry Wentland {
3314562236bSHarry Wentland 	int i;
3324562236bSHarry Wentland 
3334562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
3344562236bSHarry Wentland 		if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
3354562236bSHarry Wentland 			return res_ctx->pipe_ctx[i].clock_source;
3364562236bSHarry Wentland 	}
3374562236bSHarry Wentland 
3384562236bSHarry Wentland 	return NULL;
3394562236bSHarry Wentland }
3404562236bSHarry Wentland 
3414562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface(
3424562236bSHarry Wentland 		enum surface_pixel_format surface_pixel_format)
3434562236bSHarry Wentland {
3444562236bSHarry Wentland 	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
3454562236bSHarry Wentland 
3464562236bSHarry Wentland 	switch (surface_pixel_format) {
3474562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
3484562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_INDEX8;
3494562236bSHarry Wentland 		break;
3504562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
3514562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
3524562236bSHarry Wentland 		break;
3534562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
3544562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
3554562236bSHarry Wentland 		break;
3564562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
3574562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
3584562236bSHarry Wentland 		break;
3598693049aSTony Cheng 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
3604562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
3614562236bSHarry Wentland 		break;
3624562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
3634562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
3644562236bSHarry Wentland 		break;
3654562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
3664562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
3674562236bSHarry Wentland 		break;
3684562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
3694562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
3704562236bSHarry Wentland 		break;
3714562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
3724562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
3734562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_FP16;
3744562236bSHarry Wentland 		break;
3754562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
3764562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
3774562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_420BPP12;
3784562236bSHarry Wentland 		break;
379ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
380ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
381ffbcd19aSVitaly Prosyak 		dal_pixel_format = PIXEL_FORMAT_420BPP15;
382ffbcd19aSVitaly Prosyak 		break;
3834562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
3844562236bSHarry Wentland 	default:
3854562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
3864562236bSHarry Wentland 		break;
3874562236bSHarry Wentland 	}
3884562236bSHarry Wentland 	return dal_pixel_format;
3894562236bSHarry Wentland }
3904562236bSHarry Wentland 
3914562236bSHarry Wentland static void rect_swap_helper(struct rect *rect)
3924562236bSHarry Wentland {
3934562236bSHarry Wentland 	uint32_t temp = 0;
3944562236bSHarry Wentland 
3954562236bSHarry Wentland 	temp = rect->height;
3964562236bSHarry Wentland 	rect->height = rect->width;
3974562236bSHarry Wentland 	rect->width = temp;
3984562236bSHarry Wentland 
3994562236bSHarry Wentland 	temp = rect->x;
4004562236bSHarry Wentland 	rect->x = rect->y;
4014562236bSHarry Wentland 	rect->y = temp;
4024562236bSHarry Wentland }
4034562236bSHarry Wentland 
4044562236bSHarry Wentland static void calculate_viewport(
4054562236bSHarry Wentland 		const struct dc_surface *surface,
4064562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
4074562236bSHarry Wentland {
4084562236bSHarry Wentland 	struct rect stream_src = pipe_ctx->stream->public.src;
4094562236bSHarry Wentland 	struct rect src = surface->src_rect;
4104562236bSHarry Wentland 	struct rect dst = surface->dst_rect;
4114562236bSHarry Wentland 	struct rect surface_clip = surface->clip_rect;
4124562236bSHarry Wentland 	struct rect clip = {0};
4134562236bSHarry Wentland 
4144562236bSHarry Wentland 
4154562236bSHarry Wentland 	if (surface->rotation == ROTATION_ANGLE_90 ||
4164562236bSHarry Wentland 	    surface->rotation == ROTATION_ANGLE_270) {
4174562236bSHarry Wentland 		rect_swap_helper(&src);
4184562236bSHarry Wentland 		rect_swap_helper(&dst);
4194562236bSHarry Wentland 		rect_swap_helper(&surface_clip);
4204562236bSHarry Wentland 		rect_swap_helper(&stream_src);
4214562236bSHarry Wentland 	}
4224562236bSHarry Wentland 
4234562236bSHarry Wentland 	/* The actual clip is an intersection between stream
4244562236bSHarry Wentland 	 * source and surface clip
4254562236bSHarry Wentland 	 */
4264562236bSHarry Wentland 	clip.x = stream_src.x > surface_clip.x ?
4274562236bSHarry Wentland 			stream_src.x : surface_clip.x;
4284562236bSHarry Wentland 
4294562236bSHarry Wentland 	clip.width = stream_src.x + stream_src.width <
4304562236bSHarry Wentland 			surface_clip.x + surface_clip.width ?
4314562236bSHarry Wentland 			stream_src.x + stream_src.width - clip.x :
4324562236bSHarry Wentland 			surface_clip.x + surface_clip.width - clip.x ;
4334562236bSHarry Wentland 
4344562236bSHarry Wentland 	clip.y = stream_src.y > surface_clip.y ?
4354562236bSHarry Wentland 			stream_src.y : surface_clip.y;
4364562236bSHarry Wentland 
4374562236bSHarry Wentland 	clip.height = stream_src.y + stream_src.height <
4384562236bSHarry Wentland 			surface_clip.y + surface_clip.height ?
4394562236bSHarry Wentland 			stream_src.y + stream_src.height - clip.y :
4404562236bSHarry Wentland 			surface_clip.y + surface_clip.height - clip.y ;
4414562236bSHarry Wentland 
4424562236bSHarry Wentland 	/* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
4434562236bSHarry Wentland 	 * num_pixels = clip.num_pix * scl_ratio
4444562236bSHarry Wentland 	 */
4454562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) *
4464562236bSHarry Wentland 			src.width / dst.width;
4474562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.width = clip.width *
4484562236bSHarry Wentland 			src.width / dst.width;
4494562236bSHarry Wentland 
4504562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) *
4514562236bSHarry Wentland 			src.height / dst.height;
4524562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.height = clip.height *
4534562236bSHarry Wentland 			src.height / dst.height;
4544562236bSHarry Wentland 
4554562236bSHarry Wentland 	/* Minimum viewport such that 420/422 chroma vp is non 0 */
4564562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.width < 2)
4574562236bSHarry Wentland 		pipe_ctx->scl_data.viewport.width = 2;
4584562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.height < 2)
4594562236bSHarry Wentland 		pipe_ctx->scl_data.viewport.height = 2;
4604562236bSHarry Wentland }
4614562236bSHarry Wentland 
4624562236bSHarry Wentland static void calculate_recout(
4634562236bSHarry Wentland 		const struct dc_surface *surface,
4644562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
4654562236bSHarry Wentland {
4664562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
4674562236bSHarry Wentland 	struct rect clip = surface->clip_rect;
4684562236bSHarry Wentland 
4694562236bSHarry Wentland 	pipe_ctx->scl_data.recout.x = stream->public.dst.x;
4704562236bSHarry Wentland 	if (stream->public.src.x < clip.x)
4714562236bSHarry Wentland 		pipe_ctx->scl_data.recout.x += (clip.x
4724562236bSHarry Wentland 			- stream->public.src.x) * stream->public.dst.width
4734562236bSHarry Wentland 						/ stream->public.src.width;
4744562236bSHarry Wentland 
4754562236bSHarry Wentland 	pipe_ctx->scl_data.recout.width = clip.width *
4764562236bSHarry Wentland 			stream->public.dst.width / stream->public.src.width;
4774562236bSHarry Wentland 	if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x >
4784562236bSHarry Wentland 			stream->public.dst.x + stream->public.dst.width)
4794562236bSHarry Wentland 		pipe_ctx->scl_data.recout.width =
4804562236bSHarry Wentland 			stream->public.dst.x + stream->public.dst.width
4814562236bSHarry Wentland 						- pipe_ctx->scl_data.recout.x;
4824562236bSHarry Wentland 
4834562236bSHarry Wentland 	pipe_ctx->scl_data.recout.y = stream->public.dst.y;
4844562236bSHarry Wentland 	if (stream->public.src.y < clip.y)
4854562236bSHarry Wentland 		pipe_ctx->scl_data.recout.y += (clip.y
4864562236bSHarry Wentland 			- stream->public.src.y) * stream->public.dst.height
4874562236bSHarry Wentland 						/ stream->public.src.height;
4884562236bSHarry Wentland 
4894562236bSHarry Wentland 	pipe_ctx->scl_data.recout.height = clip.height *
4904562236bSHarry Wentland 			stream->public.dst.height / stream->public.src.height;
4914562236bSHarry Wentland 	if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y >
4924562236bSHarry Wentland 			stream->public.dst.y + stream->public.dst.height)
4934562236bSHarry Wentland 		pipe_ctx->scl_data.recout.height =
4944562236bSHarry Wentland 			stream->public.dst.y + stream->public.dst.height
4954562236bSHarry Wentland 						- pipe_ctx->scl_data.recout.y;
4964562236bSHarry Wentland }
4974562236bSHarry Wentland 
4984562236bSHarry Wentland static void calculate_scaling_ratios(
4994562236bSHarry Wentland 		const struct dc_surface *surface,
5004562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
5014562236bSHarry Wentland {
5024562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
5034562236bSHarry Wentland 	const uint32_t in_w = stream->public.src.width;
5044562236bSHarry Wentland 	const uint32_t in_h = stream->public.src.height;
5054562236bSHarry Wentland 	const uint32_t out_w = stream->public.dst.width;
5064562236bSHarry Wentland 	const uint32_t out_h = stream->public.dst.height;
5074562236bSHarry Wentland 
5084562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction(
5094562236bSHarry Wentland 					surface->src_rect.width,
5104562236bSHarry Wentland 					surface->dst_rect.width);
5114562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction(
5124562236bSHarry Wentland 					surface->src_rect.height,
5134562236bSHarry Wentland 					surface->dst_rect.height);
5144562236bSHarry Wentland 
5154562236bSHarry Wentland 	if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
5164562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz.value *= 2;
5174562236bSHarry Wentland 	else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
5184562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert.value *= 2;
5194562236bSHarry Wentland 
5204562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert.value = div64_s64(
5214562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert.value * in_h, out_h);
5224562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz.value = div64_s64(
5234562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz.value * in_w, out_w);
5244562236bSHarry Wentland 
5254562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz;
5264562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert;
5274562236bSHarry Wentland 
5284562236bSHarry Wentland 	if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) {
5294562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz_c.value /= 2;
5304562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert_c.value /= 2;
5314562236bSHarry Wentland 	}
5324562236bSHarry Wentland }
5334562236bSHarry Wentland 
5344562236bSHarry Wentland bool resource_build_scaling_params(
5354562236bSHarry Wentland 	const struct dc_surface *surface,
5364562236bSHarry Wentland 	struct pipe_ctx *pipe_ctx)
5374562236bSHarry Wentland {
5384562236bSHarry Wentland 	bool res;
5394562236bSHarry Wentland 	struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
5404562236bSHarry Wentland 	/* Important: scaling ratio calculation requires pixel format,
5414562236bSHarry Wentland 	 * lb depth calculation requires recout and taps require scaling ratios.
5424562236bSHarry Wentland 	 */
5434562236bSHarry Wentland 	pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format);
5444562236bSHarry Wentland 
5454562236bSHarry Wentland 	calculate_viewport(surface, pipe_ctx);
5464562236bSHarry Wentland 
5474562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16)
5484562236bSHarry Wentland 		return false;
5494562236bSHarry Wentland 
5504562236bSHarry Wentland 	calculate_scaling_ratios(surface, pipe_ctx);
5514562236bSHarry Wentland 
5524562236bSHarry Wentland 	calculate_recout(surface, pipe_ctx);
5534562236bSHarry Wentland 
5544562236bSHarry Wentland 	/**
5554562236bSHarry Wentland 	 * Setting line buffer pixel depth to 24bpp yields banding
5564562236bSHarry Wentland 	 * on certain displays, such as the Sharp 4k
5574562236bSHarry Wentland 	 */
5584562236bSHarry Wentland 	pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
5594562236bSHarry Wentland 
5604562236bSHarry Wentland 	pipe_ctx->scl_data.h_active = timing->h_addressable;
5614562236bSHarry Wentland 	pipe_ctx->scl_data.v_active = timing->v_addressable;
5624562236bSHarry Wentland 
5634562236bSHarry Wentland 	/* Taps calculations */
5644562236bSHarry Wentland 	res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
5654562236bSHarry Wentland 		pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
5664562236bSHarry Wentland 
5674562236bSHarry Wentland 	if (!res) {
5684562236bSHarry Wentland 		/* Try 24 bpp linebuffer */
5694562236bSHarry Wentland 		pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
5704562236bSHarry Wentland 
5714562236bSHarry Wentland 		res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
5724562236bSHarry Wentland 			pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
5734562236bSHarry Wentland 	}
5744562236bSHarry Wentland 
5754562236bSHarry Wentland 	dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
5764562236bSHarry Wentland 				"%s: Viewport:\nheight:%d width:%d x:%d "
5774562236bSHarry Wentland 				"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
5784562236bSHarry Wentland 				"y:%d\n",
5794562236bSHarry Wentland 				__func__,
5804562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.height,
5814562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.width,
5824562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.x,
5834562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.y,
5844562236bSHarry Wentland 				surface->dst_rect.height,
5854562236bSHarry Wentland 				surface->dst_rect.width,
5864562236bSHarry Wentland 				surface->dst_rect.x,
5874562236bSHarry Wentland 				surface->dst_rect.y);
5884562236bSHarry Wentland 
5894562236bSHarry Wentland 	return res;
5904562236bSHarry Wentland }
5914562236bSHarry Wentland 
5924562236bSHarry Wentland 
5934562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context(
5944562236bSHarry Wentland 	const struct core_dc *dc,
5954562236bSHarry Wentland 	struct validate_context *context)
5964562236bSHarry Wentland {
5974562236bSHarry Wentland 	int i;
5984562236bSHarry Wentland 
5994562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
6004562236bSHarry Wentland 		if (context->res_ctx.pipe_ctx[i].surface != NULL &&
6014562236bSHarry Wentland 				context->res_ctx.pipe_ctx[i].stream != NULL)
6024562236bSHarry Wentland 			if (!resource_build_scaling_params(
6034562236bSHarry Wentland 				&context->res_ctx.pipe_ctx[i].surface->public,
6044562236bSHarry Wentland 				&context->res_ctx.pipe_ctx[i]))
605f84a8161STony Cheng 				return DC_FAIL_SCALING;
6064562236bSHarry Wentland 	}
6074562236bSHarry Wentland 
6084562236bSHarry Wentland 	return DC_OK;
6094562236bSHarry Wentland }
6104562236bSHarry Wentland 
611ab2541b6SAric Cyr static void detach_surfaces_for_stream(
6124562236bSHarry Wentland 		struct validate_context *context,
613ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
6144562236bSHarry Wentland {
6154562236bSHarry Wentland 	int i;
616ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
6174562236bSHarry Wentland 
6184562236bSHarry Wentland 	for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
6194562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i];
6204562236bSHarry Wentland 		if (cur_pipe->stream == stream) {
6214562236bSHarry Wentland 			cur_pipe->surface = NULL;
6224562236bSHarry Wentland 			cur_pipe->top_pipe = NULL;
6234562236bSHarry Wentland 			cur_pipe->bottom_pipe = NULL;
6244562236bSHarry Wentland 		}
6254562236bSHarry Wentland 	}
6264562236bSHarry Wentland }
6274562236bSHarry Wentland 
6284562236bSHarry Wentland struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx)
6294562236bSHarry Wentland {
6304562236bSHarry Wentland 	int i;
6314562236bSHarry Wentland 	struct pipe_ctx *secondary_pipe = NULL;
6324562236bSHarry Wentland 
6334562236bSHarry Wentland 	/*
6344562236bSHarry Wentland 	 * search backwards for the second pipe to keep pipe
6354562236bSHarry Wentland 	 * assignment more consistent
6364562236bSHarry Wentland 	 */
6374562236bSHarry Wentland 
6384562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
6394562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == NULL) {
6404562236bSHarry Wentland 			secondary_pipe = &res_ctx->pipe_ctx[i];
6414562236bSHarry Wentland 			secondary_pipe->pipe_idx = i;
6424562236bSHarry Wentland 			break;
6434562236bSHarry Wentland 		}
6444562236bSHarry Wentland 	}
6454562236bSHarry Wentland 
6464562236bSHarry Wentland 
6474562236bSHarry Wentland 	return secondary_pipe;
6484562236bSHarry Wentland }
6494562236bSHarry Wentland 
6504562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream(
6514562236bSHarry Wentland 		struct resource_context *res_ctx,
6524562236bSHarry Wentland 		const struct core_stream *stream)
6534562236bSHarry Wentland {
6544562236bSHarry Wentland 	int i;
6554562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->pipe_count; i++) {
6564562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
6574562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].top_pipe) {
6584562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
6594562236bSHarry Wentland 			break;
6604562236bSHarry Wentland 		}
6614562236bSHarry Wentland 	}
6624562236bSHarry Wentland 	return NULL;
6634562236bSHarry Wentland }
6644562236bSHarry Wentland 
6654562236bSHarry Wentland /*
666ab2541b6SAric Cyr  * A free_pipe for a stream is defined here as a pipe
667ab2541b6SAric Cyr  * that has no surface attached yet
6684562236bSHarry Wentland  */
669ab2541b6SAric Cyr static struct pipe_ctx *acquire_free_pipe_for_stream(
6704562236bSHarry Wentland 		struct resource_context *res_ctx,
671ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
6724562236bSHarry Wentland {
6734562236bSHarry Wentland 	int i;
674ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
6754562236bSHarry Wentland 
6764562236bSHarry Wentland 	struct pipe_ctx *head_pipe = NULL;
6774562236bSHarry Wentland 
6784562236bSHarry Wentland 	/* Find head pipe, which has the back end set up*/
6794562236bSHarry Wentland 
6804562236bSHarry Wentland 	head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
6814562236bSHarry Wentland 
6824562236bSHarry Wentland 	if (!head_pipe)
6834562236bSHarry Wentland 		ASSERT(0);
6844562236bSHarry Wentland 
6854562236bSHarry Wentland 	if (!head_pipe->surface)
6864562236bSHarry Wentland 		return head_pipe;
6874562236bSHarry Wentland 
6884562236bSHarry Wentland 	/* Re-use pipe already acquired for this stream if available*/
6894562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
6904562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
6914562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].surface) {
6924562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
6934562236bSHarry Wentland 		}
6944562236bSHarry Wentland 	}
6954562236bSHarry Wentland 
6964562236bSHarry Wentland 	/*
6974562236bSHarry Wentland 	 * At this point we have no re-useable pipe for this stream and we need
6984562236bSHarry Wentland 	 * to acquire an idle one to satisfy the request
6994562236bSHarry Wentland 	 */
7004562236bSHarry Wentland 
7014562236bSHarry Wentland 	if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer)
7024562236bSHarry Wentland 		return NULL;
7034562236bSHarry Wentland 
7044562236bSHarry Wentland 	return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream);
7054562236bSHarry Wentland 
7064562236bSHarry Wentland }
7074562236bSHarry Wentland 
708ab2541b6SAric Cyr static void release_free_pipes_for_stream(
7094562236bSHarry Wentland 		struct resource_context *res_ctx,
710ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
7114562236bSHarry Wentland {
7124562236bSHarry Wentland 	int i;
713ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
7144562236bSHarry Wentland 
7154562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
7164562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
7174562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].surface) {
7184562236bSHarry Wentland 			res_ctx->pipe_ctx[i].stream = NULL;
7194562236bSHarry Wentland 		}
7204562236bSHarry Wentland 	}
7214562236bSHarry Wentland }
7224562236bSHarry Wentland 
7234562236bSHarry Wentland bool resource_attach_surfaces_to_context(
7244562236bSHarry Wentland 		const struct dc_surface * const *surfaces,
7254562236bSHarry Wentland 		int surface_count,
726ab2541b6SAric Cyr 		const struct dc_stream *dc_stream,
7274562236bSHarry Wentland 		struct validate_context *context)
7284562236bSHarry Wentland {
7294562236bSHarry Wentland 	int i;
7304562236bSHarry Wentland 	struct pipe_ctx *tail_pipe;
731ab2541b6SAric Cyr 	struct dc_stream_status *stream_status = NULL;
7324562236bSHarry Wentland 
7334562236bSHarry Wentland 
7344562236bSHarry Wentland 	if (surface_count > MAX_SURFACE_NUM) {
7354562236bSHarry Wentland 		dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
7364562236bSHarry Wentland 			surface_count, MAX_SURFACE_NUM);
7374562236bSHarry Wentland 		return false;
7384562236bSHarry Wentland 	}
7394562236bSHarry Wentland 
740ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++)
741ab2541b6SAric Cyr 		if (&context->streams[i]->public == dc_stream) {
742ab2541b6SAric Cyr 			stream_status = &context->stream_status[i];
7434562236bSHarry Wentland 			break;
7444562236bSHarry Wentland 		}
745ab2541b6SAric Cyr 	if (stream_status == NULL) {
746ab2541b6SAric Cyr 		dm_error("Existing stream not found; failed to attach surfaces\n");
7474562236bSHarry Wentland 		return false;
7484562236bSHarry Wentland 	}
7494562236bSHarry Wentland 
7504562236bSHarry Wentland 	/* retain new surfaces */
7514562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
7524562236bSHarry Wentland 		dc_surface_retain(surfaces[i]);
7534562236bSHarry Wentland 
754ab2541b6SAric Cyr 	detach_surfaces_for_stream(context, dc_stream);
7554562236bSHarry Wentland 
7564562236bSHarry Wentland 	/* release existing surfaces*/
757ab2541b6SAric Cyr 	for (i = 0; i < stream_status->surface_count; i++)
758ab2541b6SAric Cyr 		dc_surface_release(stream_status->surfaces[i]);
7594562236bSHarry Wentland 
760ab2541b6SAric Cyr 	for (i = surface_count; i < stream_status->surface_count; i++)
761ab2541b6SAric Cyr 		stream_status->surfaces[i] = NULL;
7624562236bSHarry Wentland 
763ab2541b6SAric Cyr 	stream_status->surface_count = 0;
7644562236bSHarry Wentland 
7654562236bSHarry Wentland 	if (surface_count == 0)
7664562236bSHarry Wentland 		return true;
7674562236bSHarry Wentland 
7684562236bSHarry Wentland 	tail_pipe = NULL;
7694562236bSHarry Wentland 	for (i = 0; i < surface_count; i++) {
7704562236bSHarry Wentland 		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
771ab2541b6SAric Cyr 		struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(
772ab2541b6SAric Cyr 				&context->res_ctx, dc_stream);
7734562236bSHarry Wentland 
7744562236bSHarry Wentland 		if (!free_pipe) {
775ab2541b6SAric Cyr 			stream_status->surfaces[i] = NULL;
7764562236bSHarry Wentland 			return false;
7774562236bSHarry Wentland 		}
7784562236bSHarry Wentland 
7794562236bSHarry Wentland 		free_pipe->surface = surface;
7804562236bSHarry Wentland 
7814562236bSHarry Wentland 		if (tail_pipe) {
7824562236bSHarry Wentland 			free_pipe->top_pipe = tail_pipe;
7834562236bSHarry Wentland 			tail_pipe->bottom_pipe = free_pipe;
7844562236bSHarry Wentland 		}
7854562236bSHarry Wentland 
7864562236bSHarry Wentland 		tail_pipe = free_pipe;
7874562236bSHarry Wentland 	}
7884562236bSHarry Wentland 
789ab2541b6SAric Cyr 	release_free_pipes_for_stream(&context->res_ctx, dc_stream);
7904562236bSHarry Wentland 
7914562236bSHarry Wentland 	/* assign new surfaces*/
7924562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
793ab2541b6SAric Cyr 		stream_status->surfaces[i] = surfaces[i];
7944562236bSHarry Wentland 
795ab2541b6SAric Cyr 	stream_status->surface_count = surface_count;
7964562236bSHarry Wentland 
7974562236bSHarry Wentland 	return true;
7984562236bSHarry Wentland }
7994562236bSHarry Wentland 
8004562236bSHarry Wentland 
8014562236bSHarry Wentland static bool is_timing_changed(const struct core_stream *cur_stream,
8024562236bSHarry Wentland 		const struct core_stream *new_stream)
8034562236bSHarry Wentland {
8044562236bSHarry Wentland 	if (cur_stream == NULL)
8054562236bSHarry Wentland 		return true;
8064562236bSHarry Wentland 
8074562236bSHarry Wentland 	/* If sink pointer changed, it means this is a hotplug, we should do
8084562236bSHarry Wentland 	 * full hw setting.
8094562236bSHarry Wentland 	 */
8104562236bSHarry Wentland 	if (cur_stream->sink != new_stream->sink)
8114562236bSHarry Wentland 		return true;
8124562236bSHarry Wentland 
8134562236bSHarry Wentland 	/* If output color space is changed, need to reprogram info frames */
8144562236bSHarry Wentland 	if (cur_stream->public.output_color_space !=
8154562236bSHarry Wentland 			new_stream->public.output_color_space)
8164562236bSHarry Wentland 		return true;
8174562236bSHarry Wentland 
8184562236bSHarry Wentland 	return memcmp(
8194562236bSHarry Wentland 		&cur_stream->public.timing,
8204562236bSHarry Wentland 		&new_stream->public.timing,
8214562236bSHarry Wentland 		sizeof(struct dc_crtc_timing)) != 0;
8224562236bSHarry Wentland }
8234562236bSHarry Wentland 
8244562236bSHarry Wentland static bool are_stream_backends_same(
8254562236bSHarry Wentland 	const struct core_stream *stream_a, const struct core_stream *stream_b)
8264562236bSHarry Wentland {
8274562236bSHarry Wentland 	if (stream_a == stream_b)
8284562236bSHarry Wentland 		return true;
8294562236bSHarry Wentland 
8304562236bSHarry Wentland 	if (stream_a == NULL || stream_b == NULL)
8314562236bSHarry Wentland 		return false;
8324562236bSHarry Wentland 
8334562236bSHarry Wentland 	if (is_timing_changed(stream_a, stream_b))
8344562236bSHarry Wentland 		return false;
8354562236bSHarry Wentland 
8364562236bSHarry Wentland 	return true;
8374562236bSHarry Wentland }
8384562236bSHarry Wentland 
839ab2541b6SAric Cyr bool is_stream_unchanged(
840ab2541b6SAric Cyr 	const struct core_stream *old_stream, const struct core_stream *stream)
8414562236bSHarry Wentland {
842ab2541b6SAric Cyr 	if (old_stream == stream)
8434562236bSHarry Wentland 		return true;
8444562236bSHarry Wentland 
8454562236bSHarry Wentland 	if (!are_stream_backends_same(old_stream, stream))
8464562236bSHarry Wentland 		return false;
8474562236bSHarry Wentland 
8484562236bSHarry Wentland 	return true;
8494562236bSHarry Wentland }
8504562236bSHarry Wentland 
8514562236bSHarry Wentland bool resource_validate_attach_surfaces(
8524562236bSHarry Wentland 		const struct dc_validation_set set[],
8534562236bSHarry Wentland 		int set_count,
8544562236bSHarry Wentland 		const struct validate_context *old_context,
8554562236bSHarry Wentland 		struct validate_context *context)
8564562236bSHarry Wentland {
8574562236bSHarry Wentland 	int i, j;
8584562236bSHarry Wentland 
8594562236bSHarry Wentland 	for (i = 0; i < set_count; i++) {
860ab2541b6SAric Cyr 		for (j = 0; j < old_context->stream_count; j++)
861ab2541b6SAric Cyr 			if (is_stream_unchanged(
862ab2541b6SAric Cyr 					old_context->streams[j],
863ab2541b6SAric Cyr 					context->streams[i])) {
8644562236bSHarry Wentland 				if (!resource_attach_surfaces_to_context(
865ab2541b6SAric Cyr 						old_context->stream_status[j].surfaces,
866ab2541b6SAric Cyr 						old_context->stream_status[j].surface_count,
867ab2541b6SAric Cyr 						&context->streams[i]->public,
8684562236bSHarry Wentland 						context))
8694562236bSHarry Wentland 					return false;
870ab2541b6SAric Cyr 				context->stream_status[i] = old_context->stream_status[j];
8714562236bSHarry Wentland 			}
8724562236bSHarry Wentland 		if (set[i].surface_count != 0)
8734562236bSHarry Wentland 			if (!resource_attach_surfaces_to_context(
8744562236bSHarry Wentland 					set[i].surfaces,
8754562236bSHarry Wentland 					set[i].surface_count,
876ab2541b6SAric Cyr 					&context->streams[i]->public,
8774562236bSHarry Wentland 					context))
8784562236bSHarry Wentland 				return false;
8794562236bSHarry Wentland 
8804562236bSHarry Wentland 	}
8814562236bSHarry Wentland 
8824562236bSHarry Wentland 	return true;
8834562236bSHarry Wentland }
8844562236bSHarry Wentland 
8854562236bSHarry Wentland /* Maximum TMDS single link pixel clock 165MHz */
8864562236bSHarry Wentland #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
8874562236bSHarry Wentland 
8884562236bSHarry Wentland static void set_stream_engine_in_use(
8894562236bSHarry Wentland 		struct resource_context *res_ctx,
8904562236bSHarry Wentland 		struct stream_encoder *stream_enc)
8914562236bSHarry Wentland {
8924562236bSHarry Wentland 	int i;
8934562236bSHarry Wentland 
8944562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
8954562236bSHarry Wentland 		if (res_ctx->pool->stream_enc[i] == stream_enc)
8964562236bSHarry Wentland 			res_ctx->is_stream_enc_acquired[i] = true;
8974562236bSHarry Wentland 	}
8984562236bSHarry Wentland }
8994562236bSHarry Wentland 
9004562236bSHarry Wentland /* TODO: release audio object */
9014562236bSHarry Wentland static void set_audio_in_use(
9024562236bSHarry Wentland 		struct resource_context *res_ctx,
9034562236bSHarry Wentland 		struct audio *audio)
9044562236bSHarry Wentland {
9054562236bSHarry Wentland 	int i;
9064562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->audio_count; i++) {
9074562236bSHarry Wentland 		if (res_ctx->pool->audios[i] == audio) {
9084562236bSHarry Wentland 			res_ctx->is_audio_acquired[i] = true;
9094562236bSHarry Wentland 		}
9104562236bSHarry Wentland 	}
9114562236bSHarry Wentland }
9124562236bSHarry Wentland 
9134562236bSHarry Wentland static int acquire_first_free_pipe(
9144562236bSHarry Wentland 		struct resource_context *res_ctx,
9154562236bSHarry Wentland 		struct core_stream *stream)
9164562236bSHarry Wentland {
9174562236bSHarry Wentland 	int i;
9184562236bSHarry Wentland 
9194562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->pipe_count; i++) {
9204562236bSHarry Wentland 		if (!res_ctx->pipe_ctx[i].stream) {
9214562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
9224562236bSHarry Wentland 
9234562236bSHarry Wentland 			pipe_ctx->tg = res_ctx->pool->timing_generators[i];
9244562236bSHarry Wentland 			pipe_ctx->mi = res_ctx->pool->mis[i];
9254562236bSHarry Wentland 			pipe_ctx->ipp = res_ctx->pool->ipps[i];
9264562236bSHarry Wentland 			pipe_ctx->xfm = res_ctx->pool->transforms[i];
9274562236bSHarry Wentland 			pipe_ctx->opp = res_ctx->pool->opps[i];
9284562236bSHarry Wentland 			pipe_ctx->dis_clk = res_ctx->pool->display_clock;
9294562236bSHarry Wentland 			pipe_ctx->pipe_idx = i;
9304562236bSHarry Wentland 
9314562236bSHarry Wentland 			pipe_ctx->stream = stream;
9324562236bSHarry Wentland 			return i;
9334562236bSHarry Wentland 		}
9344562236bSHarry Wentland 	}
9354562236bSHarry Wentland 	return -1;
9364562236bSHarry Wentland }
9374562236bSHarry Wentland 
9384562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link(
9394562236bSHarry Wentland 		struct resource_context *res_ctx,
9404562236bSHarry Wentland 		struct core_stream *stream)
9414562236bSHarry Wentland {
9424562236bSHarry Wentland 	int i;
9434562236bSHarry Wentland 	int j = -1;
9444562236bSHarry Wentland 	struct core_link *link = stream->sink->link;
9454562236bSHarry Wentland 
9464562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
9474562236bSHarry Wentland 		if (!res_ctx->is_stream_enc_acquired[i] &&
9484562236bSHarry Wentland 					res_ctx->pool->stream_enc[i]) {
9494562236bSHarry Wentland 			/* Store first available for MST second display
9504562236bSHarry Wentland 			 * in daisy chain use case */
9514562236bSHarry Wentland 			j = i;
9524562236bSHarry Wentland 			if (res_ctx->pool->stream_enc[i]->id ==
9534562236bSHarry Wentland 					link->link_enc->preferred_engine)
9544562236bSHarry Wentland 				return res_ctx->pool->stream_enc[i];
9554562236bSHarry Wentland 		}
9564562236bSHarry Wentland 	}
9574562236bSHarry Wentland 
9584562236bSHarry Wentland 	/*
9594562236bSHarry Wentland 	 * below can happen in cases when stream encoder is acquired:
9604562236bSHarry Wentland 	 * 1) for second MST display in chain, so preferred engine already
9614562236bSHarry Wentland 	 * acquired;
9624562236bSHarry Wentland 	 * 2) for another link, which preferred engine already acquired by any
9634562236bSHarry Wentland 	 * MST configuration.
9644562236bSHarry Wentland 	 *
9654562236bSHarry Wentland 	 * If signal is of DP type and preferred engine not found, return last available
9664562236bSHarry Wentland 	 *
9674562236bSHarry Wentland 	 * TODO - This is just a patch up and a generic solution is
9684562236bSHarry Wentland 	 * required for non DP connectors.
9694562236bSHarry Wentland 	 */
9704562236bSHarry Wentland 
9714562236bSHarry Wentland 	if (j >= 0 && dc_is_dp_signal(stream->signal))
9724562236bSHarry Wentland 		return res_ctx->pool->stream_enc[j];
9734562236bSHarry Wentland 
9744562236bSHarry Wentland 	return NULL;
9754562236bSHarry Wentland }
9764562236bSHarry Wentland 
9774562236bSHarry Wentland static struct audio *find_first_free_audio(struct resource_context *res_ctx)
9784562236bSHarry Wentland {
9794562236bSHarry Wentland 	int i;
9804562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->audio_count; i++) {
9814562236bSHarry Wentland 		if (res_ctx->is_audio_acquired[i] == false) {
9824562236bSHarry Wentland 			return res_ctx->pool->audios[i];
9834562236bSHarry Wentland 		}
9844562236bSHarry Wentland 	}
9854562236bSHarry Wentland 
9864562236bSHarry Wentland 	return 0;
9874562236bSHarry Wentland }
9884562236bSHarry Wentland 
9894562236bSHarry Wentland static void update_stream_signal(struct core_stream *stream)
9904562236bSHarry Wentland {
9914562236bSHarry Wentland 	const struct dc_sink *dc_sink = stream->public.sink;
9924562236bSHarry Wentland 
9932796eaeeSJoshua Aberback 	if (dc_sink->sink_signal == SIGNAL_TYPE_NONE)
9942796eaeeSJoshua Aberback 		stream->signal = stream->sink->link->public.connector_signal;
9952796eaeeSJoshua Aberback 	else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
9962796eaeeSJoshua Aberback 			dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK)
9974562236bSHarry Wentland 		/* For asic supports dual link DVI, we should adjust signal type
9984562236bSHarry Wentland 		 * based on timing pixel clock. If pixel clock more than 165Mhz,
9994562236bSHarry Wentland 		 * signal is dual link, otherwise, single link.
10004562236bSHarry Wentland 		 */
10012796eaeeSJoshua Aberback 		if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
10024562236bSHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
10034562236bSHarry Wentland 		else
10044562236bSHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
10052796eaeeSJoshua Aberback 	else
10062796eaeeSJoshua Aberback 		stream->signal = dc_sink->sink_signal;
10074562236bSHarry Wentland }
10084562236bSHarry Wentland 
10094562236bSHarry Wentland bool resource_is_stream_unchanged(
1010ab2541b6SAric Cyr 	const struct validate_context *old_context, const struct core_stream *stream)
10114562236bSHarry Wentland {
1012ab2541b6SAric Cyr 	int i;
10134562236bSHarry Wentland 
1014ab2541b6SAric Cyr 	for (i = 0; i < old_context->stream_count; i++) {
1015ab2541b6SAric Cyr 		const struct core_stream *old_stream = old_context->streams[i];
10164562236bSHarry Wentland 
10174562236bSHarry Wentland 		if (are_stream_backends_same(old_stream, stream))
10184562236bSHarry Wentland 				return true;
10194562236bSHarry Wentland 	}
10204562236bSHarry Wentland 
10214562236bSHarry Wentland 	return false;
10224562236bSHarry Wentland }
10234562236bSHarry Wentland 
10244562236bSHarry Wentland static void copy_pipe_ctx(
10254562236bSHarry Wentland 	const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
10264562236bSHarry Wentland {
10274562236bSHarry Wentland 	struct core_surface *surface = to_pipe_ctx->surface;
10284562236bSHarry Wentland 	struct core_stream *stream = to_pipe_ctx->stream;
10294562236bSHarry Wentland 
10304562236bSHarry Wentland 	*to_pipe_ctx = *from_pipe_ctx;
10314562236bSHarry Wentland 	to_pipe_ctx->stream = stream;
10324562236bSHarry Wentland 	if (surface != NULL)
10334562236bSHarry Wentland 		to_pipe_ctx->surface = surface;
10344562236bSHarry Wentland }
10354562236bSHarry Wentland 
10364562236bSHarry Wentland static struct core_stream *find_pll_sharable_stream(
10374562236bSHarry Wentland 		const struct core_stream *stream_needs_pll,
10384562236bSHarry Wentland 		struct validate_context *context)
10394562236bSHarry Wentland {
1040ab2541b6SAric Cyr 	int i;
10414562236bSHarry Wentland 
1042ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1043ab2541b6SAric Cyr 		struct core_stream *stream_has_pll = context->streams[i];
10444562236bSHarry Wentland 
10454562236bSHarry Wentland 		/* We are looking for non dp, non virtual stream */
10464562236bSHarry Wentland 		if (resource_are_streams_timing_synchronizable(
10474562236bSHarry Wentland 			stream_needs_pll, stream_has_pll)
10484562236bSHarry Wentland 			&& !dc_is_dp_signal(stream_has_pll->signal)
10494562236bSHarry Wentland 			&& stream_has_pll->sink->link->public.connector_signal
10504562236bSHarry Wentland 			!= SIGNAL_TYPE_VIRTUAL)
10514562236bSHarry Wentland 			return stream_has_pll;
1052ab2541b6SAric Cyr 
10534562236bSHarry Wentland 	}
10544562236bSHarry Wentland 
10554562236bSHarry Wentland 	return NULL;
10564562236bSHarry Wentland }
10574562236bSHarry Wentland 
10584562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
10594562236bSHarry Wentland {
10604562236bSHarry Wentland 	uint32_t pix_clk = timing->pix_clk_khz;
10614562236bSHarry Wentland 	uint32_t normalized_pix_clk = pix_clk;
10624562236bSHarry Wentland 
10634562236bSHarry Wentland 	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
10644562236bSHarry Wentland 		pix_clk /= 2;
1065cc4d99b8SCharlene Liu 	if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
10664562236bSHarry Wentland 		switch (timing->display_color_depth) {
10674562236bSHarry Wentland 		case COLOR_DEPTH_888:
10684562236bSHarry Wentland 			normalized_pix_clk = pix_clk;
10694562236bSHarry Wentland 			break;
10704562236bSHarry Wentland 		case COLOR_DEPTH_101010:
10714562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 30) / 24;
10724562236bSHarry Wentland 			break;
10734562236bSHarry Wentland 		case COLOR_DEPTH_121212:
10744562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 36) / 24;
10754562236bSHarry Wentland 		break;
10764562236bSHarry Wentland 		case COLOR_DEPTH_161616:
10774562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 48) / 24;
10784562236bSHarry Wentland 		break;
10794562236bSHarry Wentland 		default:
10804562236bSHarry Wentland 			ASSERT(0);
10814562236bSHarry Wentland 		break;
10824562236bSHarry Wentland 		}
1083cc4d99b8SCharlene Liu 	}
10844562236bSHarry Wentland 	return normalized_pix_clk;
10854562236bSHarry Wentland }
10864562236bSHarry Wentland 
10874562236bSHarry Wentland static void calculate_phy_pix_clks(
10884562236bSHarry Wentland 		const struct core_dc *dc,
10894562236bSHarry Wentland 		struct validate_context *context)
10904562236bSHarry Wentland {
1091ab2541b6SAric Cyr 	int i;
10924562236bSHarry Wentland 
1093ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1094ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
10954562236bSHarry Wentland 
10964562236bSHarry Wentland 		update_stream_signal(stream);
10974562236bSHarry Wentland 
10984562236bSHarry Wentland 		/* update actual pixel clock on all streams */
10994562236bSHarry Wentland 		if (dc_is_hdmi_signal(stream->signal))
11004562236bSHarry Wentland 			stream->phy_pix_clk = get_norm_pix_clk(
11014562236bSHarry Wentland 				&stream->public.timing);
11024562236bSHarry Wentland 		else
11034562236bSHarry Wentland 			stream->phy_pix_clk =
11044562236bSHarry Wentland 				stream->public.timing.pix_clk_khz;
11054562236bSHarry Wentland 	}
11064562236bSHarry Wentland }
11074562236bSHarry Wentland 
11084562236bSHarry Wentland enum dc_status resource_map_pool_resources(
11094562236bSHarry Wentland 		const struct core_dc *dc,
11104562236bSHarry Wentland 		struct validate_context *context)
11114562236bSHarry Wentland {
1112ab2541b6SAric Cyr 	int i, j;
11134562236bSHarry Wentland 
11144562236bSHarry Wentland 	calculate_phy_pix_clks(dc, context);
11154562236bSHarry Wentland 
1116ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1117ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
11184562236bSHarry Wentland 
11194b679bc3SCharlene Liu 		if (!resource_is_stream_unchanged(dc->current_context, stream)) {
11204b679bc3SCharlene Liu 			if (stream != NULL && dc->current_context->streams[i] != NULL) {
11214b679bc3SCharlene Liu 				stream->bit_depth_params =
11224b679bc3SCharlene Liu 						dc->current_context->streams[i]->bit_depth_params;
11234b679bc3SCharlene Liu 				stream->clamping = dc->current_context->streams[i]->clamping;
11244562236bSHarry Wentland 			continue;
11254b679bc3SCharlene Liu 		}
11264b679bc3SCharlene Liu 	}
11274562236bSHarry Wentland 		/* mark resources used for stream that is already active */
1128ab2541b6SAric Cyr 		for (j = 0; j < MAX_PIPES; j++) {
11294562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx =
1130ab2541b6SAric Cyr 				&context->res_ctx.pipe_ctx[j];
11314562236bSHarry Wentland 			const struct pipe_ctx *old_pipe_ctx =
1132ab2541b6SAric Cyr 				&dc->current_context->res_ctx.pipe_ctx[j];
11334562236bSHarry Wentland 
11344562236bSHarry Wentland 			if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
11354562236bSHarry Wentland 				continue;
11364562236bSHarry Wentland 
1137268cadbdSYongqiang Sun 			if (old_pipe_ctx->top_pipe)
1138268cadbdSYongqiang Sun 				continue;
1139268cadbdSYongqiang Sun 
11404562236bSHarry Wentland 			pipe_ctx->stream = stream;
11414562236bSHarry Wentland 			copy_pipe_ctx(old_pipe_ctx, pipe_ctx);
11424562236bSHarry Wentland 
11438c737fccSYongqiang Sun 			/* Split pipe resource, do not acquire back end */
11448c737fccSYongqiang Sun 			if (!pipe_ctx->stream_enc)
11458c737fccSYongqiang Sun 				continue;
11468c737fccSYongqiang Sun 
11474562236bSHarry Wentland 			set_stream_engine_in_use(
11484562236bSHarry Wentland 				&context->res_ctx,
11494562236bSHarry Wentland 				pipe_ctx->stream_enc);
11504562236bSHarry Wentland 
11514562236bSHarry Wentland 			/* Switch to dp clock source only if there is
11524562236bSHarry Wentland 			 * no non dp stream that shares the same timing
11534562236bSHarry Wentland 			 * with the dp stream.
11544562236bSHarry Wentland 			 */
11554562236bSHarry Wentland 			if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
11564562236bSHarry Wentland 				!find_pll_sharable_stream(stream, context))
11574562236bSHarry Wentland 				pipe_ctx->clock_source =
11584562236bSHarry Wentland 					context->res_ctx.pool->dp_clock_source;
11594562236bSHarry Wentland 
11604562236bSHarry Wentland 			resource_reference_clock_source(
11614562236bSHarry Wentland 				&context->res_ctx,
11624562236bSHarry Wentland 				pipe_ctx->clock_source);
11634562236bSHarry Wentland 
11644562236bSHarry Wentland 			set_audio_in_use(&context->res_ctx,
11654562236bSHarry Wentland 					 pipe_ctx->audio);
11664562236bSHarry Wentland 		}
11674562236bSHarry Wentland 	}
11684562236bSHarry Wentland 
1169ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1170ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
11714562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx = NULL;
11724562236bSHarry Wentland 		int pipe_idx = -1;
11734562236bSHarry Wentland 
11744562236bSHarry Wentland 		if (resource_is_stream_unchanged(dc->current_context, stream))
11754562236bSHarry Wentland 			continue;
11764562236bSHarry Wentland 		/* acquire new resources */
1177ab2541b6SAric Cyr 		pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream);
11784562236bSHarry Wentland 		if (pipe_idx < 0)
11794562236bSHarry Wentland 			return DC_NO_CONTROLLER_RESOURCE;
11804562236bSHarry Wentland 
11814562236bSHarry Wentland 
11824562236bSHarry Wentland 		pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
11834562236bSHarry Wentland 
11844562236bSHarry Wentland 		pipe_ctx->stream_enc =
11854562236bSHarry Wentland 			find_first_free_match_stream_enc_for_link(
11864562236bSHarry Wentland 				&context->res_ctx, stream);
11874562236bSHarry Wentland 
11884562236bSHarry Wentland 		if (!pipe_ctx->stream_enc)
11894562236bSHarry Wentland 			return DC_NO_STREAM_ENG_RESOURCE;
11904562236bSHarry Wentland 
11914562236bSHarry Wentland 		set_stream_engine_in_use(
11924562236bSHarry Wentland 			&context->res_ctx,
11934562236bSHarry Wentland 			pipe_ctx->stream_enc);
11944562236bSHarry Wentland 
11954562236bSHarry Wentland 		/* TODO: Add check if ASIC support and EDID audio */
11964a9a5d62SZeyu Fan 		if (!stream->sink->public.converter_disable_audio &&
11974562236bSHarry Wentland 			dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
11984562236bSHarry Wentland 			stream->public.audio_info.mode_count) {
11994562236bSHarry Wentland 			pipe_ctx->audio = find_first_free_audio(
12004562236bSHarry Wentland 				&context->res_ctx);
12014562236bSHarry Wentland 
12024562236bSHarry Wentland 			/*
12034562236bSHarry Wentland 			 * Audio assigned in order first come first get.
12044562236bSHarry Wentland 			 * There are asics which has number of audio
12054562236bSHarry Wentland 			 * resources less then number of pipes
12064562236bSHarry Wentland 			 */
12074562236bSHarry Wentland 			if (pipe_ctx->audio)
12084562236bSHarry Wentland 				set_audio_in_use(
12094562236bSHarry Wentland 					&context->res_ctx,
12104562236bSHarry Wentland 					pipe_ctx->audio);
12114562236bSHarry Wentland 		}
12124562236bSHarry Wentland 
1213ab2541b6SAric Cyr 		context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst;
12144562236bSHarry Wentland 	}
12154562236bSHarry Wentland 
12164562236bSHarry Wentland 	return DC_OK;
12174562236bSHarry Wentland }
12184562236bSHarry Wentland 
1219ab2541b6SAric Cyr /* first stream in the context is used to populate the rest */
1220ab2541b6SAric Cyr void validate_guaranteed_copy_streams(
12214562236bSHarry Wentland 		struct validate_context *context,
1222ab2541b6SAric Cyr 		int max_streams)
12234562236bSHarry Wentland {
12244562236bSHarry Wentland 	int i;
12254562236bSHarry Wentland 
1226ab2541b6SAric Cyr 	for (i = 1; i < max_streams; i++) {
1227ab2541b6SAric Cyr 		context->streams[i] = context->streams[0];
12284562236bSHarry Wentland 
12294562236bSHarry Wentland 		copy_pipe_ctx(&context->res_ctx.pipe_ctx[0],
12304562236bSHarry Wentland 			      &context->res_ctx.pipe_ctx[i]);
12314562236bSHarry Wentland 		context->res_ctx.pipe_ctx[i].stream =
12324562236bSHarry Wentland 				context->res_ctx.pipe_ctx[0].stream;
12334562236bSHarry Wentland 
1234ab2541b6SAric Cyr 		dc_stream_retain(&context->streams[i]->public);
1235ab2541b6SAric Cyr 		context->stream_count++;
12364562236bSHarry Wentland 	}
12374562236bSHarry Wentland }
12384562236bSHarry Wentland 
12396e4d6beeSTony Cheng static void patch_gamut_packet_checksum(
12406e4d6beeSTony Cheng 		struct encoder_info_packet *gamut_packet)
12414562236bSHarry Wentland {
12424562236bSHarry Wentland 	/* For gamut we recalc checksum */
12436e4d6beeSTony Cheng 	if (gamut_packet->valid) {
12444562236bSHarry Wentland 		uint8_t chk_sum = 0;
12454562236bSHarry Wentland 		uint8_t *ptr;
12464562236bSHarry Wentland 		uint8_t i;
12474562236bSHarry Wentland 
12484562236bSHarry Wentland 		/*start of the Gamut data. */
12496e4d6beeSTony Cheng 		ptr = &gamut_packet->sb[3];
12504562236bSHarry Wentland 
12516e4d6beeSTony Cheng 		for (i = 0; i <= gamut_packet->sb[1]; i++)
12524562236bSHarry Wentland 			chk_sum += ptr[i];
12534562236bSHarry Wentland 
12546e4d6beeSTony Cheng 		gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
12551646a6feSAndrew Wong 	}
12564562236bSHarry Wentland }
12574562236bSHarry Wentland 
12584562236bSHarry Wentland static void set_avi_info_frame(
12596e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
12604562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
12614562236bSHarry Wentland {
12624562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
12634562236bSHarry Wentland 	enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
12644562236bSHarry Wentland 	struct info_frame info_frame = { {0} };
12654562236bSHarry Wentland 	uint32_t pixel_encoding = 0;
12664562236bSHarry Wentland 	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
12674562236bSHarry Wentland 	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
12684562236bSHarry Wentland 	bool itc = false;
12694562236bSHarry Wentland 	uint8_t cn0_cn1 = 0;
12704562236bSHarry Wentland 	uint8_t *check_sum = NULL;
12714562236bSHarry Wentland 	uint8_t byte_index = 0;
12724562236bSHarry Wentland 
12734562236bSHarry Wentland 	color_space = pipe_ctx->stream->public.output_color_space;
12744562236bSHarry Wentland 
12754562236bSHarry Wentland 	/* Initialize header */
12764562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.
12773e183c5fSDave Airlie 			info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
12784562236bSHarry Wentland 	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
12794562236bSHarry Wentland 	* not be used in HDMI 2.0 (Section 10.1) */
12803e183c5fSDave Airlie 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2;
12814562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.length =
12823e183c5fSDave Airlie 			HDMI_AVI_INFOFRAME_SIZE;
12834562236bSHarry Wentland 
12844562236bSHarry Wentland 	/*
12854562236bSHarry Wentland 	 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
12864562236bSHarry Wentland 	 * according to HDMI 2.0 spec (Section 10.1)
12874562236bSHarry Wentland 	 */
12884562236bSHarry Wentland 
12894562236bSHarry Wentland 	switch (stream->public.timing.pixel_encoding) {
12904562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR422:
12914562236bSHarry Wentland 		pixel_encoding = 1;
12924562236bSHarry Wentland 		break;
12934562236bSHarry Wentland 
12944562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR444:
12954562236bSHarry Wentland 		pixel_encoding = 2;
12964562236bSHarry Wentland 		break;
12974562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR420:
12984562236bSHarry Wentland 		pixel_encoding = 3;
12994562236bSHarry Wentland 		break;
13004562236bSHarry Wentland 
13014562236bSHarry Wentland 	case PIXEL_ENCODING_RGB:
13024562236bSHarry Wentland 	default:
13034562236bSHarry Wentland 		pixel_encoding = 0;
13044562236bSHarry Wentland 	}
13054562236bSHarry Wentland 
13064562236bSHarry Wentland 	/* Y0_Y1_Y2 : The pixel encoding */
13074562236bSHarry Wentland 	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
13084562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 =
13094562236bSHarry Wentland 		pixel_encoding;
13104562236bSHarry Wentland 
13114562236bSHarry Wentland 	/* A0 = 1 Active Format Information valid */
13124562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.A0 =
13134562236bSHarry Wentland 		ACTIVE_FORMAT_VALID;
13144562236bSHarry Wentland 
13154562236bSHarry Wentland 	/* B0, B1 = 3; Bar info data is valid */
13164562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 =
13174562236bSHarry Wentland 		BAR_INFO_BOTH_VALID;
13184562236bSHarry Wentland 
13194562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 =
13204562236bSHarry Wentland 			PICTURE_SCALING_UNIFORM;
13214562236bSHarry Wentland 
13224562236bSHarry Wentland 	/* S0, S1 : Underscan / Overscan */
13234562236bSHarry Wentland 	/* TODO: un-hardcode scan type */
13244562236bSHarry Wentland 	scan_type = SCANNING_TYPE_UNDERSCAN;
13254562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type;
13264562236bSHarry Wentland 
13274562236bSHarry Wentland 	/* C0, C1 : Colorimetry */
13288fde5884SCharlene Liu 	if (color_space == COLOR_SPACE_YCBCR709 ||
13298fde5884SCharlene Liu 			color_space == COLOR_SPACE_YCBCR709_LIMITED)
13304562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13314562236bSHarry Wentland 				COLORIMETRY_ITU709;
13328fde5884SCharlene Liu 	else if (color_space == COLOR_SPACE_YCBCR601 ||
13338fde5884SCharlene Liu 			color_space == COLOR_SPACE_YCBCR601_LIMITED)
13344562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13354562236bSHarry Wentland 				COLORIMETRY_ITU601;
13368fde5884SCharlene Liu 	else {
13378fde5884SCharlene Liu 		if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB)
13388fde5884SCharlene Liu 			BREAK_TO_DEBUGGER();
13394562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13404562236bSHarry Wentland 				COLORIMETRY_NO_DATA;
13418fde5884SCharlene Liu 	}
1342534db198SAmy Zhang 	if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
1343534db198SAmy Zhang 			color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
1344534db198SAmy Zhang 			color_space == COLOR_SPACE_2020_YCBCR) {
1345534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
1346534db198SAmy Zhang 				COLORIMETRYEX_BT2020RGBYCBCR;
1347534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1348534db198SAmy Zhang 				COLORIMETRY_EXTENDED;
1349534db198SAmy Zhang 	} else if (color_space == COLOR_SPACE_ADOBERGB) {
1350534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
1351534db198SAmy Zhang 				COLORIMETRYEX_ADOBERGB;
1352534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1353534db198SAmy Zhang 				COLORIMETRY_EXTENDED;
1354534db198SAmy Zhang 	}
1355534db198SAmy Zhang 
13564562236bSHarry Wentland 	/* TODO: un-hardcode aspect ratio */
13574562236bSHarry Wentland 	aspect = stream->public.timing.aspect_ratio;
13584562236bSHarry Wentland 
13594562236bSHarry Wentland 	switch (aspect) {
13604562236bSHarry Wentland 	case ASPECT_RATIO_4_3:
13614562236bSHarry Wentland 	case ASPECT_RATIO_16_9:
13624562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect;
13634562236bSHarry Wentland 		break;
13644562236bSHarry Wentland 
13654562236bSHarry Wentland 	case ASPECT_RATIO_NO_DATA:
13664562236bSHarry Wentland 	case ASPECT_RATIO_64_27:
13674562236bSHarry Wentland 	case ASPECT_RATIO_256_135:
13684562236bSHarry Wentland 	default:
13694562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0;
13704562236bSHarry Wentland 	}
13714562236bSHarry Wentland 
13724562236bSHarry Wentland 	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
13734562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 =
13744562236bSHarry Wentland 			ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
13754562236bSHarry Wentland 
13764562236bSHarry Wentland 	/* TODO: un-hardcode cn0_cn1 and itc */
13774562236bSHarry Wentland 	cn0_cn1 = 0;
13784562236bSHarry Wentland 	itc = false;
13794562236bSHarry Wentland 
13804562236bSHarry Wentland 	if (itc) {
13814562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1;
13824562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 =
13834562236bSHarry Wentland 			cn0_cn1;
13844562236bSHarry Wentland 	}
13854562236bSHarry Wentland 
13864562236bSHarry Wentland 	/* TODO : We should handle YCC quantization */
13874562236bSHarry Wentland 	/* but we do not have matrix calculation */
13884562236bSHarry Wentland 	if (color_space == COLOR_SPACE_SRGB) {
13894562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
13904562236bSHarry Wentland 						RGB_QUANTIZATION_FULL_RANGE;
13914562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
13924562236bSHarry Wentland 						YYC_QUANTIZATION_FULL_RANGE;
13934562236bSHarry Wentland 	} else if (color_space == COLOR_SPACE_SRGB_LIMITED) {
13944562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
13954562236bSHarry Wentland 						RGB_QUANTIZATION_LIMITED_RANGE;
13964562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
13974562236bSHarry Wentland 						YYC_QUANTIZATION_LIMITED_RANGE;
13984562236bSHarry Wentland 	} else {
13994562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
14004562236bSHarry Wentland 						RGB_QUANTIZATION_DEFAULT_RANGE;
14014562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
14024562236bSHarry Wentland 						YYC_QUANTIZATION_LIMITED_RANGE;
14034562236bSHarry Wentland 	}
14044562236bSHarry Wentland 
14054562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 =
14064562236bSHarry Wentland 					stream->public.timing.vic;
14074562236bSHarry Wentland 
14084562236bSHarry Wentland 	/* pixel repetition
14094562236bSHarry Wentland 	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
14104562236bSHarry Wentland 	 * repetition start from 1 */
14114562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0;
14124562236bSHarry Wentland 
14134562236bSHarry Wentland 	/* Bar Info
14144562236bSHarry Wentland 	 * barTop:    Line Number of End of Top Bar.
14154562236bSHarry Wentland 	 * barBottom: Line Number of Start of Bottom Bar.
14164562236bSHarry Wentland 	 * barLeft:   Pixel Number of End of Left Bar.
14174562236bSHarry Wentland 	 * barRight:  Pixel Number of Start of Right Bar. */
14184562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top =
14194562236bSHarry Wentland 			stream->public.timing.v_border_top;
14204562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom =
14214562236bSHarry Wentland 		(stream->public.timing.v_border_top
14224562236bSHarry Wentland 			- stream->public.timing.v_border_bottom + 1);
14234562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left =
14244562236bSHarry Wentland 			stream->public.timing.h_border_left;
14254562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right =
14264562236bSHarry Wentland 		(stream->public.timing.h_total
14274562236bSHarry Wentland 			- stream->public.timing.h_border_right + 1);
14284562236bSHarry Wentland 
14294562236bSHarry Wentland 	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
14304562236bSHarry Wentland 	check_sum =
14314562236bSHarry Wentland 		&info_frame.
14324562236bSHarry Wentland 		avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
14333e183c5fSDave Airlie 	*check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2;
14344562236bSHarry Wentland 
14353e183c5fSDave Airlie 	for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++)
14364562236bSHarry Wentland 		*check_sum += info_frame.avi_info_packet.info_packet_hdmi.
14374562236bSHarry Wentland 				packet_raw_data.sb[byte_index];
14384562236bSHarry Wentland 
14394562236bSHarry Wentland 	/* one byte complement */
14404562236bSHarry Wentland 	*check_sum = (uint8_t) (0x100 - *check_sum);
14414562236bSHarry Wentland 
14424562236bSHarry Wentland 	/* Store in hw_path_mode */
14434562236bSHarry Wentland 	info_packet->hb0 =
14444562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0;
14454562236bSHarry Wentland 	info_packet->hb1 =
14464562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1;
14474562236bSHarry Wentland 	info_packet->hb2 =
14484562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2;
14494562236bSHarry Wentland 
1450e66e4d64SHarry Wentland 	for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet.
1451e66e4d64SHarry Wentland 				info_packet_hdmi.packet_raw_data.sb); byte_index++)
14524562236bSHarry Wentland 		info_packet->sb[byte_index] = info_frame.avi_info_packet.
14534562236bSHarry Wentland 				info_packet_hdmi.packet_raw_data.sb[byte_index];
14544562236bSHarry Wentland 
14554562236bSHarry Wentland 	info_packet->valid = true;
14564562236bSHarry Wentland }
14574562236bSHarry Wentland 
14586e4d6beeSTony Cheng static void set_vendor_info_packet(
14596e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
14606e4d6beeSTony Cheng 		struct core_stream *stream)
14614562236bSHarry Wentland {
14624562236bSHarry Wentland 	uint32_t length = 0;
14634562236bSHarry Wentland 	bool hdmi_vic_mode = false;
14644562236bSHarry Wentland 	uint8_t checksum = 0;
14654562236bSHarry Wentland 	uint32_t i = 0;
14664562236bSHarry Wentland 	enum dc_timing_3d_format format;
14674562236bSHarry Wentland 
14684562236bSHarry Wentland 	format = stream->public.timing.timing_3d_format;
14694562236bSHarry Wentland 
14704562236bSHarry Wentland 	/* Can be different depending on packet content */
14714562236bSHarry Wentland 	length = 5;
14724562236bSHarry Wentland 
14734562236bSHarry Wentland 	if (stream->public.timing.hdmi_vic != 0
14744562236bSHarry Wentland 			&& stream->public.timing.h_total >= 3840
14754562236bSHarry Wentland 			&& stream->public.timing.v_total >= 2160)
14764562236bSHarry Wentland 		hdmi_vic_mode = true;
14774562236bSHarry Wentland 
14784562236bSHarry Wentland 	/* According to HDMI 1.4a CTS, VSIF should be sent
14794562236bSHarry Wentland 	 * for both 3D stereo and HDMI VIC modes.
14804562236bSHarry Wentland 	 * For all other modes, there is no VSIF sent.  */
14814562236bSHarry Wentland 
14824562236bSHarry Wentland 	if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
14834562236bSHarry Wentland 		return;
14844562236bSHarry Wentland 
14854562236bSHarry Wentland 	/* 24bit IEEE Registration identifier (0x000c03). LSB first. */
14864562236bSHarry Wentland 	info_packet->sb[1] = 0x03;
14874562236bSHarry Wentland 	info_packet->sb[2] = 0x0C;
14884562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
14894562236bSHarry Wentland 
14904562236bSHarry Wentland 	/*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
14914562236bSHarry Wentland 	 * The value for HDMI_Video_Format are:
14924562236bSHarry Wentland 	 * 0x0 (0b000) - No additional HDMI video format is presented in this
14934562236bSHarry Wentland 	 * packet
14944562236bSHarry Wentland 	 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
14954562236bSHarry Wentland 	 * parameter follows
14964562236bSHarry Wentland 	 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
14974562236bSHarry Wentland 	 * potentially 3D_Ext_Data follows
14984562236bSHarry Wentland 	 * 0x3..0x7 (0b011..0b111) - reserved for future use */
14994562236bSHarry Wentland 	if (format != TIMING_3D_FORMAT_NONE)
15004562236bSHarry Wentland 		info_packet->sb[4] = (2 << 5);
15014562236bSHarry Wentland 	else if (hdmi_vic_mode)
15024562236bSHarry Wentland 		info_packet->sb[4] = (1 << 5);
15034562236bSHarry Wentland 
15044562236bSHarry Wentland 	/* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
15054562236bSHarry Wentland 	 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
15064562236bSHarry Wentland 	 * The value for 3D_Structure are:
15074562236bSHarry Wentland 	 * 0x0 - Frame Packing
15084562236bSHarry Wentland 	 * 0x1 - Field Alternative
15094562236bSHarry Wentland 	 * 0x2 - Line Alternative
15104562236bSHarry Wentland 	 * 0x3 - Side-by-Side (full)
15114562236bSHarry Wentland 	 * 0x4 - L + depth
15124562236bSHarry Wentland 	 * 0x5 - L + depth + graphics + graphics-depth
15134562236bSHarry Wentland 	 * 0x6 - Top-and-Bottom
15144562236bSHarry Wentland 	 * 0x7 - Reserved for future use
15154562236bSHarry Wentland 	 * 0x8 - Side-by-Side (Half)
15164562236bSHarry Wentland 	 * 0x9..0xE - Reserved for future use
15174562236bSHarry Wentland 	 * 0xF - Not used */
15184562236bSHarry Wentland 	switch (format) {
15194562236bSHarry Wentland 	case TIMING_3D_FORMAT_HW_FRAME_PACKING:
15204562236bSHarry Wentland 	case TIMING_3D_FORMAT_SW_FRAME_PACKING:
15214562236bSHarry Wentland 		info_packet->sb[5] = (0x0 << 4);
15224562236bSHarry Wentland 		break;
15234562236bSHarry Wentland 
15244562236bSHarry Wentland 	case TIMING_3D_FORMAT_SIDE_BY_SIDE:
15254562236bSHarry Wentland 	case TIMING_3D_FORMAT_SBS_SW_PACKED:
15264562236bSHarry Wentland 		info_packet->sb[5] = (0x8 << 4);
15274562236bSHarry Wentland 		length = 6;
15284562236bSHarry Wentland 		break;
15294562236bSHarry Wentland 
15304562236bSHarry Wentland 	case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
15314562236bSHarry Wentland 	case TIMING_3D_FORMAT_TB_SW_PACKED:
15324562236bSHarry Wentland 		info_packet->sb[5] = (0x6 << 4);
15334562236bSHarry Wentland 		break;
15344562236bSHarry Wentland 
15354562236bSHarry Wentland 	default:
15364562236bSHarry Wentland 		break;
15374562236bSHarry Wentland 	}
15384562236bSHarry Wentland 
15394562236bSHarry Wentland 	/*PB5: If PB4 is set to 0x1 (extended resolution format)
15404562236bSHarry Wentland 	 * fill PB5 with the correct HDMI VIC code */
15414562236bSHarry Wentland 	if (hdmi_vic_mode)
15424562236bSHarry Wentland 		info_packet->sb[5] = stream->public.timing.hdmi_vic;
15434562236bSHarry Wentland 
15444562236bSHarry Wentland 	/* Header */
15453e183c5fSDave Airlie 	info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */
15464562236bSHarry Wentland 	info_packet->hb1 = 0x01; /* Version */
15474562236bSHarry Wentland 
15484562236bSHarry Wentland 	/* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
15494562236bSHarry Wentland 	info_packet->hb2 = (uint8_t) (length);
15504562236bSHarry Wentland 
15514562236bSHarry Wentland 	/* Calculate checksum */
15524562236bSHarry Wentland 	checksum = 0;
15534562236bSHarry Wentland 	checksum += info_packet->hb0;
15544562236bSHarry Wentland 	checksum += info_packet->hb1;
15554562236bSHarry Wentland 	checksum += info_packet->hb2;
15564562236bSHarry Wentland 
15574562236bSHarry Wentland 	for (i = 1; i <= length; i++)
15584562236bSHarry Wentland 		checksum += info_packet->sb[i];
15594562236bSHarry Wentland 
15604562236bSHarry Wentland 	info_packet->sb[0] = (uint8_t) (0x100 - checksum);
15614562236bSHarry Wentland 
15624562236bSHarry Wentland 	info_packet->valid = true;
15634562236bSHarry Wentland }
15644562236bSHarry Wentland 
15656e4d6beeSTony Cheng static void set_spd_info_packet(
15666e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
15676e4d6beeSTony Cheng 		struct core_stream *stream)
15684562236bSHarry Wentland {
15694562236bSHarry Wentland 	/* SPD info packet for FreeSync */
15704562236bSHarry Wentland 
15714562236bSHarry Wentland 	unsigned char checksum = 0;
15724562236bSHarry Wentland 	unsigned int idx, payload_size = 0;
15734562236bSHarry Wentland 
15744562236bSHarry Wentland 	/* Check if Freesync is supported. Return if false. If true,
15754562236bSHarry Wentland 	 * set the corresponding bit in the info packet
15764562236bSHarry Wentland 	 */
15774562236bSHarry Wentland 	if (stream->public.freesync_ctx.supported == false)
15784562236bSHarry Wentland 		return;
15794562236bSHarry Wentland 
15804562236bSHarry Wentland 	if (dc_is_hdmi_signal(stream->signal)) {
15814562236bSHarry Wentland 
15824562236bSHarry Wentland 		/* HEADER */
15834562236bSHarry Wentland 
15844562236bSHarry Wentland 		/* HB0  = Packet Type = 0x83 (Source Product
15854562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
15864562236bSHarry Wentland 		 */
15873e183c5fSDave Airlie 		info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD;
15884562236bSHarry Wentland 
15894562236bSHarry Wentland 		/* HB1  = Version = 0x01 */
15904562236bSHarry Wentland 		info_packet->hb1 = 0x01;
15914562236bSHarry Wentland 
15924562236bSHarry Wentland 		/* HB2  = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
15934562236bSHarry Wentland 		info_packet->hb2 = 0x08;
15944562236bSHarry Wentland 
15954562236bSHarry Wentland 		payload_size = 0x08;
15964562236bSHarry Wentland 
15974562236bSHarry Wentland 	} else if (dc_is_dp_signal(stream->signal)) {
15984562236bSHarry Wentland 
15994562236bSHarry Wentland 		/* HEADER */
16004562236bSHarry Wentland 
16014562236bSHarry Wentland 		/* HB0  = Secondary-data Packet ID = 0 - Only non-zero
16024562236bSHarry Wentland 		 *	  when used to associate audio related info packets
16034562236bSHarry Wentland 		 */
16044562236bSHarry Wentland 		info_packet->hb0 = 0x00;
16054562236bSHarry Wentland 
16064562236bSHarry Wentland 		/* HB1  = Packet Type = 0x83 (Source Product
16074562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
16084562236bSHarry Wentland 		 */
16093e183c5fSDave Airlie 		info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD;
16104562236bSHarry Wentland 
16114562236bSHarry Wentland 		/* HB2  = [Bits 7:0 = Least significant eight bits -
16124562236bSHarry Wentland 		 *	  For INFOFRAME, the value must be 1Bh]
16134562236bSHarry Wentland 		 */
16144562236bSHarry Wentland 		info_packet->hb2 = 0x1B;
16154562236bSHarry Wentland 
16164562236bSHarry Wentland 		/* HB3  = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
16174562236bSHarry Wentland 		 *	  [Bits 1:0 = Most significant two bits = 0x00]
16184562236bSHarry Wentland 		 */
16194562236bSHarry Wentland 		info_packet->hb3 = 0x04;
16204562236bSHarry Wentland 
16214562236bSHarry Wentland 		payload_size = 0x1B;
16224562236bSHarry Wentland 	}
16234562236bSHarry Wentland 
16244562236bSHarry Wentland 	/* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
16254562236bSHarry Wentland 	info_packet->sb[1] = 0x1A;
16264562236bSHarry Wentland 
16274562236bSHarry Wentland 	/* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
16284562236bSHarry Wentland 	info_packet->sb[2] = 0x00;
16294562236bSHarry Wentland 
16304562236bSHarry Wentland 	/* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
16314562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
16324562236bSHarry Wentland 
16334562236bSHarry Wentland 	/* PB4 = Reserved */
16344562236bSHarry Wentland 	info_packet->sb[4] = 0x00;
16354562236bSHarry Wentland 
16364562236bSHarry Wentland 	/* PB5 = Reserved */
16374562236bSHarry Wentland 	info_packet->sb[5] = 0x00;
16384562236bSHarry Wentland 
16394562236bSHarry Wentland 	/* PB6 = [Bits 7:3 = Reserved] */
16404562236bSHarry Wentland 	info_packet->sb[6] = 0x00;
16414562236bSHarry Wentland 
16424562236bSHarry Wentland 	if (stream->public.freesync_ctx.supported == true)
16434562236bSHarry Wentland 		/* PB6 = [Bit 0 = FreeSync Supported] */
16444562236bSHarry Wentland 		info_packet->sb[6] |= 0x01;
16454562236bSHarry Wentland 
16464562236bSHarry Wentland 	if (stream->public.freesync_ctx.enabled == true)
16474562236bSHarry Wentland 		/* PB6 = [Bit 1 = FreeSync Enabled] */
16484562236bSHarry Wentland 		info_packet->sb[6] |= 0x02;
16494562236bSHarry Wentland 
16504562236bSHarry Wentland 	if (stream->public.freesync_ctx.active == true)
16514562236bSHarry Wentland 		/* PB6 = [Bit 2 = FreeSync Active] */
16524562236bSHarry Wentland 		info_packet->sb[6] |= 0x04;
16534562236bSHarry Wentland 
16544562236bSHarry Wentland 	/* PB7 = FreeSync Minimum refresh rate (Hz) */
16554562236bSHarry Wentland 	info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx.
16564562236bSHarry Wentland 			min_refresh_in_micro_hz / 1000000);
16574562236bSHarry Wentland 
16584562236bSHarry Wentland 	/* PB8 = FreeSync Maximum refresh rate (Hz)
16594562236bSHarry Wentland 	 *
16604562236bSHarry Wentland 	 * Note: We do not use the maximum capable refresh rate
16614562236bSHarry Wentland 	 * of the panel, because we should never go above the field
16624562236bSHarry Wentland 	 * rate of the mode timing set.
16634562236bSHarry Wentland 	 */
16644562236bSHarry Wentland 	info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx.
16654562236bSHarry Wentland 			nominal_refresh_in_micro_hz / 1000000);
16664562236bSHarry Wentland 
16674562236bSHarry Wentland 	/* PB9 - PB27  = Reserved */
16684562236bSHarry Wentland 	for (idx = 9; idx <= 27; idx++)
16694562236bSHarry Wentland 		info_packet->sb[idx] = 0x00;
16704562236bSHarry Wentland 
16714562236bSHarry Wentland 	/* Calculate checksum */
16724562236bSHarry Wentland 	checksum += info_packet->hb0;
16734562236bSHarry Wentland 	checksum += info_packet->hb1;
16744562236bSHarry Wentland 	checksum += info_packet->hb2;
16754562236bSHarry Wentland 	checksum += info_packet->hb3;
16764562236bSHarry Wentland 
16774562236bSHarry Wentland 	for (idx = 1; idx <= payload_size; idx++)
16784562236bSHarry Wentland 		checksum += info_packet->sb[idx];
16794562236bSHarry Wentland 
16804562236bSHarry Wentland 	/* PB0 = Checksum (one byte complement) */
16814562236bSHarry Wentland 	info_packet->sb[0] = (unsigned char) (0x100 - checksum);
16824562236bSHarry Wentland 
16834562236bSHarry Wentland 	info_packet->valid = true;
16844562236bSHarry Wentland }
16854562236bSHarry Wentland 
16861646a6feSAndrew Wong static void set_hdr_static_info_packet(
16876e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
16881646a6feSAndrew Wong 		struct core_surface *surface,
16896e4d6beeSTony Cheng 		struct core_stream *stream)
16901646a6feSAndrew Wong {
1691e5cf325bSHarry Wentland 	uint16_t i = 0;
16921646a6feSAndrew Wong 	enum signal_type signal = stream->signal;
1693e5cf325bSHarry Wentland 	struct dc_hdr_static_metadata hdr_metadata;
1694e5cf325bSHarry Wentland 	uint32_t data;
16951646a6feSAndrew Wong 
16961646a6feSAndrew Wong 	if (!surface)
16971646a6feSAndrew Wong 		return;
16981646a6feSAndrew Wong 
1699e5cf325bSHarry Wentland 	hdr_metadata = surface->public.hdr_static_ctx;
17001646a6feSAndrew Wong 
170170063a59SAmy Zhang 	if (!hdr_metadata.hdr_supported)
170210bff005SYongqiang Sun 		return;
170310bff005SYongqiang Sun 
17041646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
17051646a6feSAndrew Wong 		info_packet->valid = true;
17061646a6feSAndrew Wong 
17071646a6feSAndrew Wong 		info_packet->hb0 = 0x87;
17081646a6feSAndrew Wong 		info_packet->hb1 = 0x01;
17091646a6feSAndrew Wong 		info_packet->hb2 = 0x1A;
17101646a6feSAndrew Wong 		i = 1;
17111646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
17121646a6feSAndrew Wong 		info_packet->valid = true;
17131646a6feSAndrew Wong 
17141646a6feSAndrew Wong 		info_packet->hb0 = 0x00;
17151646a6feSAndrew Wong 		info_packet->hb1 = 0x87;
17161646a6feSAndrew Wong 		info_packet->hb2 = 0x1D;
17171646a6feSAndrew Wong 		info_packet->hb3 = (0x13 << 2);
17181646a6feSAndrew Wong 		i = 2;
17191646a6feSAndrew Wong 	}
17201646a6feSAndrew Wong 
17211646a6feSAndrew Wong 	data = hdr_metadata.is_hdr;
17221646a6feSAndrew Wong 	info_packet->sb[i++] = data ? 0x02 : 0x00;
17231646a6feSAndrew Wong 	info_packet->sb[i++] = 0x00;
17241646a6feSAndrew Wong 
17251646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_x / 2;
17261646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17271646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17281646a6feSAndrew Wong 
17291646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_y / 2;
17301646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17311646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17321646a6feSAndrew Wong 
17331646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_x / 2;
17341646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17351646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17361646a6feSAndrew Wong 
17371646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_y / 2;
17381646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17391646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17401646a6feSAndrew Wong 
17411646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_x / 2;
17421646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17431646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17441646a6feSAndrew Wong 
17451646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_y / 2;
17461646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17471646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17481646a6feSAndrew Wong 
17491646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_x / 2;
17501646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17511646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17521646a6feSAndrew Wong 
17531646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_y / 2;
17541646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17551646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17561646a6feSAndrew Wong 
17571646a6feSAndrew Wong 	data = hdr_metadata.max_luminance;
17581646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17591646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17601646a6feSAndrew Wong 
17611646a6feSAndrew Wong 	data = hdr_metadata.min_luminance;
17621646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17631646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17641646a6feSAndrew Wong 
17651646a6feSAndrew Wong 	data = hdr_metadata.maximum_content_light_level;
17661646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17671646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17681646a6feSAndrew Wong 
17691646a6feSAndrew Wong 	data = hdr_metadata.maximum_frame_average_light_level;
17701646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17711646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17721646a6feSAndrew Wong 
17731646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
17741646a6feSAndrew Wong 		uint32_t checksum = 0;
17751646a6feSAndrew Wong 
17761646a6feSAndrew Wong 		checksum += info_packet->hb0;
17771646a6feSAndrew Wong 		checksum += info_packet->hb1;
17781646a6feSAndrew Wong 		checksum += info_packet->hb2;
17791646a6feSAndrew Wong 
17801646a6feSAndrew Wong 		for (i = 1; i <= info_packet->hb2; i++)
17811646a6feSAndrew Wong 			checksum += info_packet->sb[i];
17821646a6feSAndrew Wong 
17831646a6feSAndrew Wong 		info_packet->sb[0] = 0x100 - checksum;
17841646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
17851646a6feSAndrew Wong 		info_packet->sb[0] = 0x01;
17861646a6feSAndrew Wong 		info_packet->sb[1] = 0x1A;
17871646a6feSAndrew Wong 	}
17881646a6feSAndrew Wong }
17891646a6feSAndrew Wong 
17906e4d6beeSTony Cheng static void set_vsc_info_packet(
17916e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
17926e4d6beeSTony Cheng 		struct core_stream *stream)
17934562236bSHarry Wentland {
17944562236bSHarry Wentland 	unsigned int vscPacketRevision = 0;
17954562236bSHarry Wentland 	unsigned int i;
17964562236bSHarry Wentland 
17974562236bSHarry Wentland 	if (stream->sink->link->public.psr_caps.psr_version != 0) {
17984562236bSHarry Wentland 		vscPacketRevision = 2;
17994562236bSHarry Wentland 	}
18004562236bSHarry Wentland 
18014562236bSHarry Wentland 	/* VSC packet not needed based on the features
18024562236bSHarry Wentland 	 * supported by this DP display
18034562236bSHarry Wentland 	 */
18044562236bSHarry Wentland 	if (vscPacketRevision == 0)
18054562236bSHarry Wentland 		return;
18064562236bSHarry Wentland 
18074562236bSHarry Wentland 	if (vscPacketRevision == 0x2) {
18084562236bSHarry Wentland 		/* Secondary-data Packet ID = 0*/
18094562236bSHarry Wentland 		info_packet->hb0 = 0x00;
18104562236bSHarry Wentland 		/* 07h - Packet Type Value indicating Video
18114562236bSHarry Wentland 		 * Stream Configuration packet
18124562236bSHarry Wentland 		 */
18134562236bSHarry Wentland 		info_packet->hb1 = 0x07;
18144562236bSHarry Wentland 		/* 02h = VSC SDP supporting 3D stereo and PSR
18154562236bSHarry Wentland 		 * (applies to eDP v1.3 or higher).
18164562236bSHarry Wentland 		 */
18174562236bSHarry Wentland 		info_packet->hb2 = 0x02;
18184562236bSHarry Wentland 		/* 08h = VSC packet supporting 3D stereo + PSR
18194562236bSHarry Wentland 		 * (HB2 = 02h).
18204562236bSHarry Wentland 		 */
18214562236bSHarry Wentland 		info_packet->hb3 = 0x08;
18224562236bSHarry Wentland 
18234562236bSHarry Wentland 		for (i = 0; i < 28; i++)
18244562236bSHarry Wentland 			info_packet->sb[i] = 0;
18254562236bSHarry Wentland 
18264562236bSHarry Wentland 		info_packet->valid = true;
18274562236bSHarry Wentland 	}
18284562236bSHarry Wentland 
18294562236bSHarry Wentland 	/*TODO: stereo 3D support and extend pixel encoding colorimetry*/
18304562236bSHarry Wentland }
18314562236bSHarry Wentland 
18324562236bSHarry Wentland void resource_validate_ctx_destruct(struct validate_context *context)
18334562236bSHarry Wentland {
18344562236bSHarry Wentland 	int i, j;
18354562236bSHarry Wentland 
1836ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1837ab2541b6SAric Cyr 		for (j = 0; j < context->stream_status[i].surface_count; j++)
18384562236bSHarry Wentland 			dc_surface_release(
1839ab2541b6SAric Cyr 				context->stream_status[i].surfaces[j]);
18404562236bSHarry Wentland 
1841ab2541b6SAric Cyr 		context->stream_status[i].surface_count = 0;
1842ab2541b6SAric Cyr 		dc_stream_release(&context->streams[i]->public);
1843ab2541b6SAric Cyr 		context->streams[i] = NULL;
18444562236bSHarry Wentland 	}
18454562236bSHarry Wentland }
18464562236bSHarry Wentland 
18474562236bSHarry Wentland /*
1848ab2541b6SAric Cyr  * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced
18494562236bSHarry Wentland  * by the src_ctx
18504562236bSHarry Wentland  */
18514562236bSHarry Wentland void resource_validate_ctx_copy_construct(
18524562236bSHarry Wentland 		const struct validate_context *src_ctx,
18534562236bSHarry Wentland 		struct validate_context *dst_ctx)
18544562236bSHarry Wentland {
18554562236bSHarry Wentland 	int i, j;
18564562236bSHarry Wentland 
18574562236bSHarry Wentland 	*dst_ctx = *src_ctx;
18584562236bSHarry Wentland 
18594562236bSHarry Wentland 	for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) {
18604562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
18614562236bSHarry Wentland 
18624562236bSHarry Wentland 		if (cur_pipe->top_pipe)
18634562236bSHarry Wentland 			cur_pipe->top_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
18644562236bSHarry Wentland 
18654562236bSHarry Wentland 		if (cur_pipe->bottom_pipe)
18664562236bSHarry Wentland 			cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
18674562236bSHarry Wentland 
18684562236bSHarry Wentland 	}
18694562236bSHarry Wentland 
1870ab2541b6SAric Cyr 	for (i = 0; i < dst_ctx->stream_count; i++) {
1871ab2541b6SAric Cyr 		dc_stream_retain(&dst_ctx->streams[i]->public);
1872ab2541b6SAric Cyr 		for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++)
18734562236bSHarry Wentland 			dc_surface_retain(
1874ab2541b6SAric Cyr 				dst_ctx->stream_status[i].surfaces[j]);
18754562236bSHarry Wentland 	}
18764562236bSHarry Wentland }
18774562236bSHarry Wentland 
18784562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll(
18794562236bSHarry Wentland 		struct resource_context *res_ctx)
18804562236bSHarry Wentland {
18814562236bSHarry Wentland 	int i;
18824562236bSHarry Wentland 
18834562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; ++i) {
18844562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
18854562236bSHarry Wentland 			return res_ctx->pool->clock_sources[i];
18864562236bSHarry Wentland 	}
18874562236bSHarry Wentland 
18884562236bSHarry Wentland 	return NULL;
18894562236bSHarry Wentland }
18904562236bSHarry Wentland 
18914562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
18924562236bSHarry Wentland {
18934562236bSHarry Wentland 	enum signal_type signal = SIGNAL_TYPE_NONE;
18946e4d6beeSTony Cheng 	struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame;
18954562236bSHarry Wentland 
18964562236bSHarry Wentland 	/* default all packets to invalid */
18976e4d6beeSTony Cheng 	info->avi.valid = false;
18986e4d6beeSTony Cheng 	info->gamut.valid = false;
18996e4d6beeSTony Cheng 	info->vendor.valid = false;
19006e4d6beeSTony Cheng 	info->hdrsmd.valid = false;
19016e4d6beeSTony Cheng 	info->vsc.valid = false;
19024562236bSHarry Wentland 
19034562236bSHarry Wentland 	signal = pipe_ctx->stream->signal;
19044562236bSHarry Wentland 
19054562236bSHarry Wentland 	/* HDMi and DP have different info packets*/
19064562236bSHarry Wentland 	if (dc_is_hdmi_signal(signal)) {
19076e4d6beeSTony Cheng 		set_avi_info_frame(&info->avi, pipe_ctx);
19086e4d6beeSTony Cheng 
19096e4d6beeSTony Cheng 		set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
19106e4d6beeSTony Cheng 
19116e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
19126e4d6beeSTony Cheng 
19136e4d6beeSTony Cheng 		set_hdr_static_info_packet(&info->hdrsmd,
19146e4d6beeSTony Cheng 				pipe_ctx->surface, pipe_ctx->stream);
19156e4d6beeSTony Cheng 
1916a33fa99dSHarry Wentland 	} else if (dc_is_dp_signal(signal)) {
19176e4d6beeSTony Cheng 		set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
19186e4d6beeSTony Cheng 
19196e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
19206e4d6beeSTony Cheng 
19216e4d6beeSTony Cheng 		set_hdr_static_info_packet(&info->hdrsmd,
19226e4d6beeSTony Cheng 				pipe_ctx->surface, pipe_ctx->stream);
1923a33fa99dSHarry Wentland 	}
19244562236bSHarry Wentland 
19256e4d6beeSTony Cheng 	patch_gamut_packet_checksum(&info->gamut);
19264562236bSHarry Wentland }
19274562236bSHarry Wentland 
19284562236bSHarry Wentland enum dc_status resource_map_clock_resources(
19294562236bSHarry Wentland 		const struct core_dc *dc,
19304562236bSHarry Wentland 		struct validate_context *context)
19314562236bSHarry Wentland {
1932ab2541b6SAric Cyr 	int i, j;
19334562236bSHarry Wentland 
19344562236bSHarry Wentland 	/* acquire new resources */
1935ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1936ab2541b6SAric Cyr 		const struct core_stream *stream = context->streams[i];
19374562236bSHarry Wentland 
19384562236bSHarry Wentland 		if (resource_is_stream_unchanged(dc->current_context, stream))
19394562236bSHarry Wentland 			continue;
19404562236bSHarry Wentland 
1941ab2541b6SAric Cyr 		for (j = 0; j < MAX_PIPES; j++) {
19424562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx =
1943ab2541b6SAric Cyr 				&context->res_ctx.pipe_ctx[j];
19444562236bSHarry Wentland 
1945ab2541b6SAric Cyr 			if (context->res_ctx.pipe_ctx[j].stream != stream)
19464562236bSHarry Wentland 				continue;
19474562236bSHarry Wentland 
19484562236bSHarry Wentland 			if (dc_is_dp_signal(pipe_ctx->stream->signal)
19494562236bSHarry Wentland 				|| pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
19504562236bSHarry Wentland 				pipe_ctx->clock_source =
19514562236bSHarry Wentland 					context->res_ctx.pool->dp_clock_source;
19524562236bSHarry Wentland 			else {
19534562236bSHarry Wentland 				pipe_ctx->clock_source = NULL;
19544562236bSHarry Wentland 
19554562236bSHarry Wentland 				if (!dc->public.config.disable_disp_pll_sharing)
19564562236bSHarry Wentland 					resource_find_used_clk_src_for_sharing(
19574562236bSHarry Wentland 						&context->res_ctx,
19584562236bSHarry Wentland 						pipe_ctx);
19594562236bSHarry Wentland 
19604562236bSHarry Wentland 				if (pipe_ctx->clock_source == NULL)
19614562236bSHarry Wentland 					pipe_ctx->clock_source =
19624562236bSHarry Wentland 						dc_resource_find_first_free_pll(&context->res_ctx);
19634562236bSHarry Wentland 			}
19644562236bSHarry Wentland 
19654562236bSHarry Wentland 			if (pipe_ctx->clock_source == NULL)
19664562236bSHarry Wentland 				return DC_NO_CLOCK_SOURCE_RESOURCE;
19674562236bSHarry Wentland 
19684562236bSHarry Wentland 			resource_reference_clock_source(
19694562236bSHarry Wentland 				&context->res_ctx,
19704562236bSHarry Wentland 				pipe_ctx->clock_source);
19714562236bSHarry Wentland 
19724562236bSHarry Wentland 			/* only one cs per stream regardless of mpo */
19734562236bSHarry Wentland 			break;
19744562236bSHarry Wentland 		}
19754562236bSHarry Wentland 	}
19764562236bSHarry Wentland 
19774562236bSHarry Wentland 	return DC_OK;
19784562236bSHarry Wentland }
19794562236bSHarry Wentland 
19804562236bSHarry Wentland /*
19814562236bSHarry Wentland  * Note: We need to disable output if clock sources change,
19824562236bSHarry Wentland  * since bios does optimization and doesn't apply if changing
19834562236bSHarry Wentland  * PHY when not already disabled.
19844562236bSHarry Wentland  */
19854562236bSHarry Wentland bool pipe_need_reprogram(
19864562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx_old,
19874562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
19884562236bSHarry Wentland {
19894562236bSHarry Wentland 	if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
19904562236bSHarry Wentland 		return true;
19914562236bSHarry Wentland 
19924562236bSHarry Wentland 	if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
19934562236bSHarry Wentland 		return true;
19944562236bSHarry Wentland 
19954562236bSHarry Wentland 	if (pipe_ctx_old->audio != pipe_ctx->audio)
19964562236bSHarry Wentland 		return true;
19974562236bSHarry Wentland 
19984562236bSHarry Wentland 	if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
19994562236bSHarry Wentland 			&& pipe_ctx_old->stream != pipe_ctx->stream)
20004562236bSHarry Wentland 		return true;
20014562236bSHarry Wentland 
20024562236bSHarry Wentland 	if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc)
20034562236bSHarry Wentland 		return true;
20044562236bSHarry Wentland 
20054562236bSHarry Wentland 	if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
20064562236bSHarry Wentland 		return true;
20074562236bSHarry Wentland 
20084562236bSHarry Wentland 
20094562236bSHarry Wentland 	return false;
20104562236bSHarry Wentland }
2011