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"
344562236bSHarry Wentland #include "set_mode_types.h"
354562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h"
364562236bSHarry Wentland 
374562236bSHarry Wentland #include "dce80/dce80_resource.h"
384562236bSHarry Wentland #include "dce100/dce100_resource.h"
394562236bSHarry Wentland #include "dce110/dce110_resource.h"
404562236bSHarry Wentland #include "dce112/dce112_resource.h"
414562236bSHarry Wentland 
424562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
434562236bSHarry Wentland {
444562236bSHarry Wentland 	enum dce_version dc_version = DCE_VERSION_UNKNOWN;
454562236bSHarry Wentland 	switch (asic_id.chip_family) {
464562236bSHarry Wentland 
474562236bSHarry Wentland 	case FAMILY_CI:
484562236bSHarry Wentland 	case FAMILY_KV:
494562236bSHarry Wentland 		dc_version = DCE_VERSION_8_0;
504562236bSHarry Wentland 		break;
514562236bSHarry Wentland 	case FAMILY_CZ:
524562236bSHarry Wentland 		dc_version = DCE_VERSION_11_0;
534562236bSHarry Wentland 		break;
544562236bSHarry Wentland 
554562236bSHarry Wentland 	case FAMILY_VI:
564562236bSHarry Wentland 		if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
574562236bSHarry Wentland 				ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
584562236bSHarry Wentland 			dc_version = DCE_VERSION_10_0;
594562236bSHarry Wentland 			break;
604562236bSHarry Wentland 		}
614562236bSHarry Wentland 		if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
62b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
63b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
644562236bSHarry Wentland 			dc_version = DCE_VERSION_11_2;
654562236bSHarry Wentland 		}
664562236bSHarry Wentland 		break;
674562236bSHarry Wentland 	default:
684562236bSHarry Wentland 		dc_version = DCE_VERSION_UNKNOWN;
694562236bSHarry Wentland 		break;
704562236bSHarry Wentland 	}
714562236bSHarry Wentland 	return dc_version;
724562236bSHarry Wentland }
734562236bSHarry Wentland 
744562236bSHarry Wentland struct resource_pool *dc_create_resource_pool(
754562236bSHarry Wentland 				struct core_dc *dc,
764562236bSHarry Wentland 				int num_virtual_links,
774562236bSHarry Wentland 				enum dce_version dc_version,
784562236bSHarry Wentland 				struct hw_asic_id asic_id)
794562236bSHarry Wentland {
804562236bSHarry Wentland 
814562236bSHarry Wentland 	switch (dc_version) {
824562236bSHarry Wentland 	case DCE_VERSION_8_0:
834562236bSHarry Wentland 		return dce80_create_resource_pool(
844562236bSHarry Wentland 			num_virtual_links, dc);
854562236bSHarry Wentland 	case DCE_VERSION_10_0:
864562236bSHarry Wentland 		return dce100_create_resource_pool(
874562236bSHarry Wentland 				num_virtual_links, dc);
884562236bSHarry Wentland 	case DCE_VERSION_11_0:
894562236bSHarry Wentland 		return dce110_create_resource_pool(
904562236bSHarry Wentland 			num_virtual_links, dc, asic_id);
914562236bSHarry Wentland 	case DCE_VERSION_11_2:
924562236bSHarry Wentland 		return dce112_create_resource_pool(
934562236bSHarry Wentland 			num_virtual_links, dc);
944562236bSHarry Wentland 	default:
954562236bSHarry Wentland 		break;
964562236bSHarry Wentland 	}
974562236bSHarry Wentland 
984562236bSHarry Wentland 	return false;
994562236bSHarry Wentland }
1004562236bSHarry Wentland 
1014562236bSHarry Wentland void dc_destroy_resource_pool(struct core_dc *dc)
1024562236bSHarry Wentland {
1034562236bSHarry Wentland 	if (dc) {
1044562236bSHarry Wentland 		if (dc->res_pool)
1054562236bSHarry Wentland 			dc->res_pool->funcs->destroy(&dc->res_pool);
1064562236bSHarry Wentland 
1074562236bSHarry Wentland 		if (dc->hwseq)
1084562236bSHarry Wentland 			dm_free(dc->hwseq);
1094562236bSHarry Wentland 	}
1104562236bSHarry Wentland }
1114562236bSHarry Wentland 
1124562236bSHarry Wentland static void update_num_audio(
1134562236bSHarry Wentland 	const struct resource_straps *straps,
1144562236bSHarry Wentland 	unsigned int *num_audio,
1154562236bSHarry Wentland 	struct audio_support *aud_support)
1164562236bSHarry Wentland {
1174562236bSHarry Wentland 	if (straps->hdmi_disable == 0) {
1184562236bSHarry Wentland 		aud_support->hdmi_audio_native = true;
1194562236bSHarry Wentland 		aud_support->hdmi_audio_on_dongle = true;
1204562236bSHarry Wentland 		aud_support->dp_audio = true;
1214562236bSHarry Wentland 	} else {
1224562236bSHarry Wentland 		if (straps->dc_pinstraps_audio & 0x2) {
1234562236bSHarry Wentland 			aud_support->hdmi_audio_on_dongle = true;
1244562236bSHarry Wentland 			aud_support->dp_audio = true;
1254562236bSHarry Wentland 		} else {
1264562236bSHarry Wentland 			aud_support->dp_audio = true;
1274562236bSHarry Wentland 		}
1284562236bSHarry Wentland 	}
1294562236bSHarry Wentland 
1304562236bSHarry Wentland 	switch (straps->audio_stream_number) {
1314562236bSHarry Wentland 	case 0: /* multi streams supported */
1324562236bSHarry Wentland 		break;
1334562236bSHarry Wentland 	case 1: /* multi streams not supported */
1344562236bSHarry Wentland 		*num_audio = 1;
1354562236bSHarry Wentland 		break;
1364562236bSHarry Wentland 	default:
1374562236bSHarry Wentland 		DC_ERR("DC: unexpected audio fuse!\n");
1384562236bSHarry Wentland 	};
1394562236bSHarry Wentland }
1404562236bSHarry Wentland 
1414562236bSHarry Wentland bool resource_construct(
1424562236bSHarry Wentland 	unsigned int num_virtual_links,
1434562236bSHarry Wentland 	struct core_dc *dc,
1444562236bSHarry Wentland 	struct resource_pool *pool,
1454562236bSHarry Wentland 	const struct resource_create_funcs *create_funcs)
1464562236bSHarry Wentland {
1474562236bSHarry Wentland 	struct dc_context *ctx = dc->ctx;
1484562236bSHarry Wentland 	const struct resource_caps *caps = pool->res_cap;
1494562236bSHarry Wentland 	int i;
1504562236bSHarry Wentland 	unsigned int num_audio = caps->num_audio;
1514562236bSHarry Wentland 	struct resource_straps straps = {0};
1524562236bSHarry Wentland 
1534562236bSHarry Wentland 	if (create_funcs->read_dce_straps)
1544562236bSHarry Wentland 		create_funcs->read_dce_straps(dc->ctx, &straps);
1554562236bSHarry Wentland 
1564562236bSHarry Wentland 	pool->audio_count = 0;
1574562236bSHarry Wentland 	if (create_funcs->create_audio) {
1584562236bSHarry Wentland 		/* find the total number of streams available via the
1594562236bSHarry Wentland 		 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
1604562236bSHarry Wentland 		 * registers (one for each pin) starting from pin 1
1614562236bSHarry Wentland 		 * up to the max number of audio pins.
1624562236bSHarry Wentland 		 * We stop on the first pin where
1634562236bSHarry Wentland 		 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
1644562236bSHarry Wentland 		 */
1654562236bSHarry Wentland 		update_num_audio(&straps, &num_audio, &pool->audio_support);
1664562236bSHarry Wentland 		for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
1674562236bSHarry Wentland 			struct audio *aud = create_funcs->create_audio(ctx, i);
1684562236bSHarry Wentland 
1694562236bSHarry Wentland 			if (aud == NULL) {
1704562236bSHarry Wentland 				DC_ERR("DC: failed to create audio!\n");
1714562236bSHarry Wentland 				return false;
1724562236bSHarry Wentland 			}
1734562236bSHarry Wentland 
1744562236bSHarry Wentland 			if (!aud->funcs->endpoint_valid(aud)) {
1754562236bSHarry Wentland 				aud->funcs->destroy(&aud);
1764562236bSHarry Wentland 				break;
1774562236bSHarry Wentland 			}
1784562236bSHarry Wentland 
1794562236bSHarry Wentland 			pool->audios[i] = aud;
1804562236bSHarry Wentland 			pool->audio_count++;
1814562236bSHarry Wentland 		}
1824562236bSHarry Wentland 	}
1834562236bSHarry Wentland 
1844562236bSHarry Wentland 	pool->stream_enc_count = 0;
1854562236bSHarry Wentland 	if (create_funcs->create_stream_encoder) {
1864562236bSHarry Wentland 		for (i = 0; i < caps->num_stream_encoder; i++) {
1874562236bSHarry Wentland 			pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
1884562236bSHarry Wentland 			if (pool->stream_enc[i] == NULL)
1894562236bSHarry Wentland 				DC_ERR("DC: failed to create stream_encoder!\n");
1904562236bSHarry Wentland 			pool->stream_enc_count++;
1914562236bSHarry Wentland 		}
1924562236bSHarry Wentland 	}
1934562236bSHarry Wentland 
1944562236bSHarry Wentland 	for (i = 0; i < num_virtual_links; i++) {
1954562236bSHarry Wentland 		pool->stream_enc[pool->stream_enc_count] =
1964562236bSHarry Wentland 			virtual_stream_encoder_create(
1974562236bSHarry Wentland 					ctx, ctx->dc_bios);
1984562236bSHarry Wentland 		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
1994562236bSHarry Wentland 			DC_ERR("DC: failed to create stream_encoder!\n");
2004562236bSHarry Wentland 			return false;
2014562236bSHarry Wentland 		}
2024562236bSHarry Wentland 		pool->stream_enc_count++;
2034562236bSHarry Wentland 	}
2044562236bSHarry Wentland 
2054562236bSHarry Wentland 	dc->hwseq = create_funcs->create_hwseq(ctx);
2064562236bSHarry Wentland 
2074562236bSHarry Wentland 	return true;
2084562236bSHarry Wentland }
2094562236bSHarry Wentland 
2104562236bSHarry Wentland 
2114562236bSHarry Wentland void resource_unreference_clock_source(
2124562236bSHarry Wentland 		struct resource_context *res_ctx,
2138c737fccSYongqiang Sun 		struct clock_source **clock_source)
2144562236bSHarry Wentland {
2154562236bSHarry Wentland 	int i;
2164562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; i++) {
2178c737fccSYongqiang Sun 		if (res_ctx->pool->clock_sources[i] != *clock_source)
2184562236bSHarry Wentland 			continue;
2194562236bSHarry Wentland 
2204562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]--;
2214562236bSHarry Wentland 
2224562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
2238c737fccSYongqiang Sun 			(*clock_source)->funcs->cs_power_down(*clock_source);
2244562236bSHarry Wentland 
2254562236bSHarry Wentland 		break;
2264562236bSHarry Wentland 	}
2274562236bSHarry Wentland 
2288c737fccSYongqiang Sun 	if (res_ctx->pool->dp_clock_source == *clock_source) {
2294562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count--;
2304562236bSHarry Wentland 
2314562236bSHarry Wentland 		if (res_ctx->dp_clock_source_ref_count == 0)
2328c737fccSYongqiang Sun 			(*clock_source)->funcs->cs_power_down(*clock_source);
2334562236bSHarry Wentland 	}
2348c737fccSYongqiang Sun 	*clock_source = NULL;
2354562236bSHarry Wentland }
2364562236bSHarry Wentland 
2374562236bSHarry Wentland void resource_reference_clock_source(
2384562236bSHarry Wentland 		struct resource_context *res_ctx,
2394562236bSHarry Wentland 		struct clock_source *clock_source)
2404562236bSHarry Wentland {
2414562236bSHarry Wentland 	int i;
2424562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; i++) {
2434562236bSHarry Wentland 		if (res_ctx->pool->clock_sources[i] != clock_source)
2444562236bSHarry Wentland 			continue;
2454562236bSHarry Wentland 
2464562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]++;
2474562236bSHarry Wentland 		break;
2484562236bSHarry Wentland 	}
2494562236bSHarry Wentland 
2504562236bSHarry Wentland 	if (res_ctx->pool->dp_clock_source == clock_source)
2514562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count++;
2524562236bSHarry Wentland }
2534562236bSHarry Wentland 
2544562236bSHarry Wentland bool resource_are_streams_timing_synchronizable(
2554562236bSHarry Wentland 	const struct core_stream *stream1,
2564562236bSHarry Wentland 	const struct core_stream *stream2)
2574562236bSHarry Wentland {
2584562236bSHarry Wentland 	if (stream1->public.timing.h_total != stream2->public.timing.h_total)
2594562236bSHarry Wentland 		return false;
2604562236bSHarry Wentland 
2614562236bSHarry Wentland 	if (stream1->public.timing.v_total != stream2->public.timing.v_total)
2624562236bSHarry Wentland 		return false;
2634562236bSHarry Wentland 
2644562236bSHarry Wentland 	if (stream1->public.timing.h_addressable
2654562236bSHarry Wentland 				!= stream2->public.timing.h_addressable)
2664562236bSHarry Wentland 		return false;
2674562236bSHarry Wentland 
2684562236bSHarry Wentland 	if (stream1->public.timing.v_addressable
2694562236bSHarry Wentland 				!= stream2->public.timing.v_addressable)
2704562236bSHarry Wentland 		return false;
2714562236bSHarry Wentland 
2724562236bSHarry Wentland 	if (stream1->public.timing.pix_clk_khz
2734562236bSHarry Wentland 				!= stream2->public.timing.pix_clk_khz)
2744562236bSHarry Wentland 		return false;
2754562236bSHarry Wentland 
2764562236bSHarry Wentland 	if (stream1->phy_pix_clk != stream2->phy_pix_clk
2774562236bSHarry Wentland 			&& !dc_is_dp_signal(stream1->signal)
2784562236bSHarry Wentland 			&& !dc_is_dp_signal(stream2->signal))
2794562236bSHarry Wentland 		return false;
2804562236bSHarry Wentland 
2814562236bSHarry Wentland 	return true;
2824562236bSHarry Wentland }
2834562236bSHarry Wentland 
2844562236bSHarry Wentland static bool is_sharable_clk_src(
2854562236bSHarry Wentland 	const struct pipe_ctx *pipe_with_clk_src,
2864562236bSHarry Wentland 	const struct pipe_ctx *pipe)
2874562236bSHarry Wentland {
2884562236bSHarry Wentland 	if (pipe_with_clk_src->clock_source == NULL)
2894562236bSHarry Wentland 		return false;
2904562236bSHarry Wentland 
2914562236bSHarry Wentland 	if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
2924562236bSHarry Wentland 		return false;
2934562236bSHarry Wentland 
2944562236bSHarry Wentland 	if (dc_is_dp_signal(pipe_with_clk_src->stream->signal))
2954562236bSHarry Wentland 		return false;
2964562236bSHarry Wentland 
2974562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
2984562236bSHarry Wentland 			&& dc_is_dvi_signal(pipe->stream->signal))
2994562236bSHarry Wentland 		return false;
3004562236bSHarry Wentland 
3014562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe->stream->signal)
3024562236bSHarry Wentland 			&& dc_is_dvi_signal(pipe_with_clk_src->stream->signal))
3034562236bSHarry Wentland 		return false;
3044562236bSHarry Wentland 
3054562236bSHarry Wentland 	if (!resource_are_streams_timing_synchronizable(
3064562236bSHarry Wentland 			pipe_with_clk_src->stream, pipe->stream))
3074562236bSHarry Wentland 		return false;
3084562236bSHarry Wentland 
3094562236bSHarry Wentland 	return true;
3104562236bSHarry Wentland }
3114562236bSHarry Wentland 
3124562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing(
3134562236bSHarry Wentland 					struct resource_context *res_ctx,
3144562236bSHarry Wentland 					struct pipe_ctx *pipe_ctx)
3154562236bSHarry Wentland {
3164562236bSHarry Wentland 	int i;
3174562236bSHarry Wentland 
3184562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
3194562236bSHarry Wentland 		if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
3204562236bSHarry Wentland 			return res_ctx->pipe_ctx[i].clock_source;
3214562236bSHarry Wentland 	}
3224562236bSHarry Wentland 
3234562236bSHarry Wentland 	return NULL;
3244562236bSHarry Wentland }
3254562236bSHarry Wentland 
3264562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface(
3274562236bSHarry Wentland 		enum surface_pixel_format surface_pixel_format)
3284562236bSHarry Wentland {
3294562236bSHarry Wentland 	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
3304562236bSHarry Wentland 
3314562236bSHarry Wentland 	switch (surface_pixel_format) {
3324562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
3334562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_INDEX8;
3344562236bSHarry Wentland 		break;
3354562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
3364562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
3374562236bSHarry Wentland 		break;
3384562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
3394562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
3404562236bSHarry Wentland 		break;
3414562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
3424562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
3434562236bSHarry Wentland 		break;
3444562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
3454562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
3464562236bSHarry Wentland 		break;
3474562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
3484562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
3494562236bSHarry Wentland 		break;
3504562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
3514562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
3524562236bSHarry Wentland 		break;
3534562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
3544562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
3554562236bSHarry Wentland 		break;
3564562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
3574562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
3584562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_FP16;
3594562236bSHarry Wentland 		break;
3604562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
3614562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_420BPP12;
3624562236bSHarry Wentland 		break;
3634562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
3644562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_420BPP12;
3654562236bSHarry Wentland 		break;
3664562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
3674562236bSHarry Wentland 	default:
3684562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
3694562236bSHarry Wentland 		break;
3704562236bSHarry Wentland 	}
3714562236bSHarry Wentland 	return dal_pixel_format;
3724562236bSHarry Wentland }
3734562236bSHarry Wentland 
3744562236bSHarry Wentland static void rect_swap_helper(struct rect *rect)
3754562236bSHarry Wentland {
3764562236bSHarry Wentland 	uint32_t temp = 0;
3774562236bSHarry Wentland 
3784562236bSHarry Wentland 	temp = rect->height;
3794562236bSHarry Wentland 	rect->height = rect->width;
3804562236bSHarry Wentland 	rect->width = temp;
3814562236bSHarry Wentland 
3824562236bSHarry Wentland 	temp = rect->x;
3834562236bSHarry Wentland 	rect->x = rect->y;
3844562236bSHarry Wentland 	rect->y = temp;
3854562236bSHarry Wentland }
3864562236bSHarry Wentland 
3874562236bSHarry Wentland static void calculate_viewport(
3884562236bSHarry Wentland 		const struct dc_surface *surface,
3894562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
3904562236bSHarry Wentland {
3914562236bSHarry Wentland 	struct rect stream_src = pipe_ctx->stream->public.src;
3924562236bSHarry Wentland 	struct rect src = surface->src_rect;
3934562236bSHarry Wentland 	struct rect dst = surface->dst_rect;
3944562236bSHarry Wentland 	struct rect surface_clip = surface->clip_rect;
3954562236bSHarry Wentland 	struct rect clip = {0};
3964562236bSHarry Wentland 
3974562236bSHarry Wentland 
3984562236bSHarry Wentland 	if (surface->rotation == ROTATION_ANGLE_90 ||
3994562236bSHarry Wentland 	    surface->rotation == ROTATION_ANGLE_270) {
4004562236bSHarry Wentland 		rect_swap_helper(&src);
4014562236bSHarry Wentland 		rect_swap_helper(&dst);
4024562236bSHarry Wentland 		rect_swap_helper(&surface_clip);
4034562236bSHarry Wentland 		rect_swap_helper(&stream_src);
4044562236bSHarry Wentland 	}
4054562236bSHarry Wentland 
4064562236bSHarry Wentland 	/* The actual clip is an intersection between stream
4074562236bSHarry Wentland 	 * source and surface clip
4084562236bSHarry Wentland 	 */
4094562236bSHarry Wentland 	clip.x = stream_src.x > surface_clip.x ?
4104562236bSHarry Wentland 			stream_src.x : surface_clip.x;
4114562236bSHarry Wentland 
4124562236bSHarry Wentland 	clip.width = stream_src.x + stream_src.width <
4134562236bSHarry Wentland 			surface_clip.x + surface_clip.width ?
4144562236bSHarry Wentland 			stream_src.x + stream_src.width - clip.x :
4154562236bSHarry Wentland 			surface_clip.x + surface_clip.width - clip.x ;
4164562236bSHarry Wentland 
4174562236bSHarry Wentland 	clip.y = stream_src.y > surface_clip.y ?
4184562236bSHarry Wentland 			stream_src.y : surface_clip.y;
4194562236bSHarry Wentland 
4204562236bSHarry Wentland 	clip.height = stream_src.y + stream_src.height <
4214562236bSHarry Wentland 			surface_clip.y + surface_clip.height ?
4224562236bSHarry Wentland 			stream_src.y + stream_src.height - clip.y :
4234562236bSHarry Wentland 			surface_clip.y + surface_clip.height - clip.y ;
4244562236bSHarry Wentland 
4254562236bSHarry Wentland 	/* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
4264562236bSHarry Wentland 	 * num_pixels = clip.num_pix * scl_ratio
4274562236bSHarry Wentland 	 */
4284562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) *
4294562236bSHarry Wentland 			src.width / dst.width;
4304562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.width = clip.width *
4314562236bSHarry Wentland 			src.width / dst.width;
4324562236bSHarry Wentland 
4334562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) *
4344562236bSHarry Wentland 			src.height / dst.height;
4354562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.height = clip.height *
4364562236bSHarry Wentland 			src.height / dst.height;
4374562236bSHarry Wentland 
4384562236bSHarry Wentland 	/* Minimum viewport such that 420/422 chroma vp is non 0 */
4394562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.width < 2)
4404562236bSHarry Wentland 		pipe_ctx->scl_data.viewport.width = 2;
4414562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.height < 2)
4424562236bSHarry Wentland 		pipe_ctx->scl_data.viewport.height = 2;
4434562236bSHarry Wentland }
4444562236bSHarry Wentland 
4454562236bSHarry Wentland static void calculate_recout(
4464562236bSHarry Wentland 		const struct dc_surface *surface,
4474562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
4484562236bSHarry Wentland {
4494562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
4504562236bSHarry Wentland 	struct rect clip = surface->clip_rect;
4514562236bSHarry Wentland 
4524562236bSHarry Wentland 	pipe_ctx->scl_data.recout.x = stream->public.dst.x;
4534562236bSHarry Wentland 	if (stream->public.src.x < clip.x)
4544562236bSHarry Wentland 		pipe_ctx->scl_data.recout.x += (clip.x
4554562236bSHarry Wentland 			- stream->public.src.x) * stream->public.dst.width
4564562236bSHarry Wentland 						/ stream->public.src.width;
4574562236bSHarry Wentland 
4584562236bSHarry Wentland 	pipe_ctx->scl_data.recout.width = clip.width *
4594562236bSHarry Wentland 			stream->public.dst.width / stream->public.src.width;
4604562236bSHarry Wentland 	if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x >
4614562236bSHarry Wentland 			stream->public.dst.x + stream->public.dst.width)
4624562236bSHarry Wentland 		pipe_ctx->scl_data.recout.width =
4634562236bSHarry Wentland 			stream->public.dst.x + stream->public.dst.width
4644562236bSHarry Wentland 						- pipe_ctx->scl_data.recout.x;
4654562236bSHarry Wentland 
4664562236bSHarry Wentland 	pipe_ctx->scl_data.recout.y = stream->public.dst.y;
4674562236bSHarry Wentland 	if (stream->public.src.y < clip.y)
4684562236bSHarry Wentland 		pipe_ctx->scl_data.recout.y += (clip.y
4694562236bSHarry Wentland 			- stream->public.src.y) * stream->public.dst.height
4704562236bSHarry Wentland 						/ stream->public.src.height;
4714562236bSHarry Wentland 
4724562236bSHarry Wentland 	pipe_ctx->scl_data.recout.height = clip.height *
4734562236bSHarry Wentland 			stream->public.dst.height / stream->public.src.height;
4744562236bSHarry Wentland 	if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y >
4754562236bSHarry Wentland 			stream->public.dst.y + stream->public.dst.height)
4764562236bSHarry Wentland 		pipe_ctx->scl_data.recout.height =
4774562236bSHarry Wentland 			stream->public.dst.y + stream->public.dst.height
4784562236bSHarry Wentland 						- pipe_ctx->scl_data.recout.y;
4794562236bSHarry Wentland }
4804562236bSHarry Wentland 
4814562236bSHarry Wentland static void calculate_scaling_ratios(
4824562236bSHarry Wentland 		const struct dc_surface *surface,
4834562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
4844562236bSHarry Wentland {
4854562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
4864562236bSHarry Wentland 	const uint32_t in_w = stream->public.src.width;
4874562236bSHarry Wentland 	const uint32_t in_h = stream->public.src.height;
4884562236bSHarry Wentland 	const uint32_t out_w = stream->public.dst.width;
4894562236bSHarry Wentland 	const uint32_t out_h = stream->public.dst.height;
4904562236bSHarry Wentland 
4914562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction(
4924562236bSHarry Wentland 					surface->src_rect.width,
4934562236bSHarry Wentland 					surface->dst_rect.width);
4944562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction(
4954562236bSHarry Wentland 					surface->src_rect.height,
4964562236bSHarry Wentland 					surface->dst_rect.height);
4974562236bSHarry Wentland 
4984562236bSHarry Wentland 	if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
4994562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz.value *= 2;
5004562236bSHarry Wentland 	else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
5014562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert.value *= 2;
5024562236bSHarry Wentland 
5034562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert.value = div64_s64(
5044562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert.value * in_h, out_h);
5054562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz.value = div64_s64(
5064562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz.value * in_w, out_w);
5074562236bSHarry Wentland 
5084562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz;
5094562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert;
5104562236bSHarry Wentland 
5114562236bSHarry Wentland 	if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) {
5124562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz_c.value /= 2;
5134562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert_c.value /= 2;
5144562236bSHarry Wentland 	}
5154562236bSHarry Wentland }
5164562236bSHarry Wentland 
5174562236bSHarry Wentland bool resource_build_scaling_params(
5184562236bSHarry Wentland 	const struct dc_surface *surface,
5194562236bSHarry Wentland 	struct pipe_ctx *pipe_ctx)
5204562236bSHarry Wentland {
5214562236bSHarry Wentland 	bool res;
5224562236bSHarry Wentland 	struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
5234562236bSHarry Wentland 	/* Important: scaling ratio calculation requires pixel format,
5244562236bSHarry Wentland 	 * lb depth calculation requires recout and taps require scaling ratios.
5254562236bSHarry Wentland 	 */
5264562236bSHarry Wentland 	pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format);
5274562236bSHarry Wentland 
5284562236bSHarry Wentland 	calculate_viewport(surface, pipe_ctx);
5294562236bSHarry Wentland 
5304562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16)
5314562236bSHarry Wentland 		return false;
5324562236bSHarry Wentland 
5334562236bSHarry Wentland 	calculate_scaling_ratios(surface, pipe_ctx);
5344562236bSHarry Wentland 
5354562236bSHarry Wentland 	calculate_recout(surface, pipe_ctx);
5364562236bSHarry Wentland 
5374562236bSHarry Wentland 	/**
5384562236bSHarry Wentland 	 * Setting line buffer pixel depth to 24bpp yields banding
5394562236bSHarry Wentland 	 * on certain displays, such as the Sharp 4k
5404562236bSHarry Wentland 	 */
5414562236bSHarry Wentland 	pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
5424562236bSHarry Wentland 
5434562236bSHarry Wentland 	pipe_ctx->scl_data.h_active = timing->h_addressable;
5444562236bSHarry Wentland 	pipe_ctx->scl_data.v_active = timing->v_addressable;
5454562236bSHarry Wentland 
5464562236bSHarry Wentland 	/* Taps calculations */
5474562236bSHarry Wentland 	res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
5484562236bSHarry Wentland 		pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
5494562236bSHarry Wentland 
5504562236bSHarry Wentland 	if (!res) {
5514562236bSHarry Wentland 		/* Try 24 bpp linebuffer */
5524562236bSHarry Wentland 		pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
5534562236bSHarry Wentland 
5544562236bSHarry Wentland 		res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
5554562236bSHarry Wentland 			pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
5564562236bSHarry Wentland 	}
5574562236bSHarry Wentland 
5584562236bSHarry Wentland 	dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
5594562236bSHarry Wentland 				"%s: Viewport:\nheight:%d width:%d x:%d "
5604562236bSHarry Wentland 				"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
5614562236bSHarry Wentland 				"y:%d\n",
5624562236bSHarry Wentland 				__func__,
5634562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.height,
5644562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.width,
5654562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.x,
5664562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.y,
5674562236bSHarry Wentland 				surface->dst_rect.height,
5684562236bSHarry Wentland 				surface->dst_rect.width,
5694562236bSHarry Wentland 				surface->dst_rect.x,
5704562236bSHarry Wentland 				surface->dst_rect.y);
5714562236bSHarry Wentland 
5724562236bSHarry Wentland 	return res;
5734562236bSHarry Wentland }
5744562236bSHarry Wentland 
5754562236bSHarry Wentland 
5764562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context(
5774562236bSHarry Wentland 	const struct core_dc *dc,
5784562236bSHarry Wentland 	struct validate_context *context)
5794562236bSHarry Wentland {
5804562236bSHarry Wentland 	int i;
5814562236bSHarry Wentland 
5824562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
5834562236bSHarry Wentland 		if (context->res_ctx.pipe_ctx[i].surface != NULL &&
5844562236bSHarry Wentland 				context->res_ctx.pipe_ctx[i].stream != NULL)
5854562236bSHarry Wentland 			if (!resource_build_scaling_params(
5864562236bSHarry Wentland 				&context->res_ctx.pipe_ctx[i].surface->public,
5874562236bSHarry Wentland 				&context->res_ctx.pipe_ctx[i]))
5884562236bSHarry Wentland 				return DC_FAIL_BANDWIDTH_VALIDATE;
5894562236bSHarry Wentland 	}
5904562236bSHarry Wentland 
5914562236bSHarry Wentland 	return DC_OK;
5924562236bSHarry Wentland }
5934562236bSHarry Wentland 
5944562236bSHarry Wentland static void detach_surfaces_for_target(
5954562236bSHarry Wentland 		struct validate_context *context,
5964562236bSHarry Wentland 		const struct dc_target *dc_target)
5974562236bSHarry Wentland {
5984562236bSHarry Wentland 	int i;
5994562236bSHarry Wentland 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]);
6004562236bSHarry Wentland 
6014562236bSHarry Wentland 	for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
6024562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i];
6034562236bSHarry Wentland 		if (cur_pipe->stream == stream) {
6044562236bSHarry Wentland 			cur_pipe->surface = NULL;
6054562236bSHarry Wentland 			cur_pipe->top_pipe = NULL;
6064562236bSHarry Wentland 			cur_pipe->bottom_pipe = NULL;
6074562236bSHarry Wentland 		}
6084562236bSHarry Wentland 	}
6094562236bSHarry Wentland }
6104562236bSHarry Wentland 
6114562236bSHarry Wentland struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx)
6124562236bSHarry Wentland {
6134562236bSHarry Wentland 	int i;
6144562236bSHarry Wentland 	struct pipe_ctx *secondary_pipe = NULL;
6154562236bSHarry Wentland 
6164562236bSHarry Wentland 	/*
6174562236bSHarry Wentland 	 * search backwards for the second pipe to keep pipe
6184562236bSHarry Wentland 	 * assignment more consistent
6194562236bSHarry Wentland 	 */
6204562236bSHarry Wentland 
6214562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
6224562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == NULL) {
6234562236bSHarry Wentland 			secondary_pipe = &res_ctx->pipe_ctx[i];
6244562236bSHarry Wentland 			secondary_pipe->pipe_idx = i;
6254562236bSHarry Wentland 			break;
6264562236bSHarry Wentland 		}
6274562236bSHarry Wentland 	}
6284562236bSHarry Wentland 
6294562236bSHarry Wentland 
6304562236bSHarry Wentland 	return secondary_pipe;
6314562236bSHarry Wentland }
6324562236bSHarry Wentland 
6334562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream(
6344562236bSHarry Wentland 		struct resource_context *res_ctx,
6354562236bSHarry Wentland 		const struct core_stream *stream)
6364562236bSHarry Wentland {
6374562236bSHarry Wentland 	int i;
6384562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->pipe_count; i++) {
6394562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
6404562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].top_pipe) {
6414562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
6424562236bSHarry Wentland 			break;
6434562236bSHarry Wentland 		}
6444562236bSHarry Wentland 	}
6454562236bSHarry Wentland 	return NULL;
6464562236bSHarry Wentland }
6474562236bSHarry Wentland 
6484562236bSHarry Wentland /*
6494562236bSHarry Wentland  * A free_pipe for a target is defined here as a pipe with a stream that belongs
6504562236bSHarry Wentland  * to the target but has no surface attached yet
6514562236bSHarry Wentland  */
6524562236bSHarry Wentland static struct pipe_ctx *acquire_free_pipe_for_target(
6534562236bSHarry Wentland 		struct resource_context *res_ctx,
6544562236bSHarry Wentland 		const struct dc_target *dc_target)
6554562236bSHarry Wentland {
6564562236bSHarry Wentland 	int i;
6574562236bSHarry Wentland 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]);
6584562236bSHarry Wentland 
6594562236bSHarry Wentland 	struct pipe_ctx *head_pipe = NULL;
6604562236bSHarry Wentland 
6614562236bSHarry Wentland 	/* Find head pipe, which has the back end set up*/
6624562236bSHarry Wentland 
6634562236bSHarry Wentland 	head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
6644562236bSHarry Wentland 
6654562236bSHarry Wentland 	if (!head_pipe)
6664562236bSHarry Wentland 		ASSERT(0);
6674562236bSHarry Wentland 
6684562236bSHarry Wentland 	if (!head_pipe->surface)
6694562236bSHarry Wentland 		return head_pipe;
6704562236bSHarry Wentland 
6714562236bSHarry Wentland 	/* Re-use pipe already acquired for this stream if available*/
6724562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
6734562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
6744562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].surface) {
6754562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
6764562236bSHarry Wentland 		}
6774562236bSHarry Wentland 	}
6784562236bSHarry Wentland 
6794562236bSHarry Wentland 	/*
6804562236bSHarry Wentland 	 * At this point we have no re-useable pipe for this stream and we need
6814562236bSHarry Wentland 	 * to acquire an idle one to satisfy the request
6824562236bSHarry Wentland 	 */
6834562236bSHarry Wentland 
6844562236bSHarry Wentland 	if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer)
6854562236bSHarry Wentland 		return NULL;
6864562236bSHarry Wentland 
6874562236bSHarry Wentland 	return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream);
6884562236bSHarry Wentland 
6894562236bSHarry Wentland }
6904562236bSHarry Wentland 
6914562236bSHarry Wentland static void release_free_pipes_for_target(
6924562236bSHarry Wentland 		struct resource_context *res_ctx,
6934562236bSHarry Wentland 		const struct dc_target *dc_target)
6944562236bSHarry Wentland {
6954562236bSHarry Wentland 	int i;
6964562236bSHarry Wentland 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]);
6974562236bSHarry Wentland 
6984562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
6994562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
7004562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].surface) {
7014562236bSHarry Wentland 			res_ctx->pipe_ctx[i].stream = NULL;
7024562236bSHarry Wentland 		}
7034562236bSHarry Wentland 	}
7044562236bSHarry Wentland }
7054562236bSHarry Wentland 
7064562236bSHarry Wentland bool resource_attach_surfaces_to_context(
7074562236bSHarry Wentland 		const struct dc_surface * const *surfaces,
7084562236bSHarry Wentland 		int surface_count,
7094562236bSHarry Wentland 		const struct dc_target *dc_target,
7104562236bSHarry Wentland 		struct validate_context *context)
7114562236bSHarry Wentland {
7124562236bSHarry Wentland 	int i;
7134562236bSHarry Wentland 	struct pipe_ctx *tail_pipe;
7144562236bSHarry Wentland 	struct dc_target_status *target_status = NULL;
7154562236bSHarry Wentland 
7164562236bSHarry Wentland 
7174562236bSHarry Wentland 	if (surface_count > MAX_SURFACE_NUM) {
7184562236bSHarry Wentland 		dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
7194562236bSHarry Wentland 			surface_count, MAX_SURFACE_NUM);
7204562236bSHarry Wentland 		return false;
7214562236bSHarry Wentland 	}
7224562236bSHarry Wentland 
7234562236bSHarry Wentland 	for (i = 0; i < context->target_count; i++)
7244562236bSHarry Wentland 		if (&context->targets[i]->public == dc_target) {
7254562236bSHarry Wentland 			target_status = &context->target_status[i];
7264562236bSHarry Wentland 			break;
7274562236bSHarry Wentland 		}
7284562236bSHarry Wentland 	if (target_status == NULL) {
7294562236bSHarry Wentland 		dm_error("Existing target not found; failed to attach surfaces\n");
7304562236bSHarry Wentland 		return false;
7314562236bSHarry Wentland 	}
7324562236bSHarry Wentland 
7334562236bSHarry Wentland 	/* retain new surfaces */
7344562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
7354562236bSHarry Wentland 		dc_surface_retain(surfaces[i]);
7364562236bSHarry Wentland 
7374562236bSHarry Wentland 	detach_surfaces_for_target(context, dc_target);
7384562236bSHarry Wentland 
7394562236bSHarry Wentland 	/* release existing surfaces*/
7404562236bSHarry Wentland 	for (i = 0; i < target_status->surface_count; i++)
7414562236bSHarry Wentland 		dc_surface_release(target_status->surfaces[i]);
7424562236bSHarry Wentland 
7434562236bSHarry Wentland 	for (i = surface_count; i < target_status->surface_count; i++)
7444562236bSHarry Wentland 		target_status->surfaces[i] = NULL;
7454562236bSHarry Wentland 
7464562236bSHarry Wentland 	target_status->surface_count = 0;
7474562236bSHarry Wentland 
7484562236bSHarry Wentland 	if (surface_count == 0)
7494562236bSHarry Wentland 		return true;
7504562236bSHarry Wentland 
7514562236bSHarry Wentland 	tail_pipe = NULL;
7524562236bSHarry Wentland 	for (i = 0; i < surface_count; i++) {
7534562236bSHarry Wentland 		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
7544562236bSHarry Wentland 		struct pipe_ctx *free_pipe = acquire_free_pipe_for_target(
7554562236bSHarry Wentland 				&context->res_ctx, dc_target);
7564562236bSHarry Wentland 
7574562236bSHarry Wentland 		if (!free_pipe) {
7584562236bSHarry Wentland 			target_status->surfaces[i] = NULL;
7594562236bSHarry Wentland 			return false;
7604562236bSHarry Wentland 		}
7614562236bSHarry Wentland 
7624562236bSHarry Wentland 		free_pipe->surface = surface;
7634562236bSHarry Wentland 
7644562236bSHarry Wentland 		if (tail_pipe) {
7654562236bSHarry Wentland 			free_pipe->top_pipe = tail_pipe;
7664562236bSHarry Wentland 			tail_pipe->bottom_pipe = free_pipe;
7674562236bSHarry Wentland 		}
7684562236bSHarry Wentland 
7694562236bSHarry Wentland 		tail_pipe = free_pipe;
7704562236bSHarry Wentland 	}
7714562236bSHarry Wentland 
7724562236bSHarry Wentland 	release_free_pipes_for_target(&context->res_ctx, dc_target);
7734562236bSHarry Wentland 
7744562236bSHarry Wentland 	/* assign new surfaces*/
7754562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
7764562236bSHarry Wentland 		target_status->surfaces[i] = surfaces[i];
7774562236bSHarry Wentland 
7784562236bSHarry Wentland 	target_status->surface_count = surface_count;
7794562236bSHarry Wentland 
7804562236bSHarry Wentland 	return true;
7814562236bSHarry Wentland }
7824562236bSHarry Wentland 
7834562236bSHarry Wentland 
7844562236bSHarry Wentland static bool is_timing_changed(const struct core_stream *cur_stream,
7854562236bSHarry Wentland 		const struct core_stream *new_stream)
7864562236bSHarry Wentland {
7874562236bSHarry Wentland 	if (cur_stream == NULL)
7884562236bSHarry Wentland 		return true;
7894562236bSHarry Wentland 
7904562236bSHarry Wentland 	/* If sink pointer changed, it means this is a hotplug, we should do
7914562236bSHarry Wentland 	 * full hw setting.
7924562236bSHarry Wentland 	 */
7934562236bSHarry Wentland 	if (cur_stream->sink != new_stream->sink)
7944562236bSHarry Wentland 		return true;
7954562236bSHarry Wentland 
7964562236bSHarry Wentland 	/* If output color space is changed, need to reprogram info frames */
7974562236bSHarry Wentland 	if (cur_stream->public.output_color_space !=
7984562236bSHarry Wentland 			new_stream->public.output_color_space)
7994562236bSHarry Wentland 		return true;
8004562236bSHarry Wentland 
8014562236bSHarry Wentland 	return memcmp(
8024562236bSHarry Wentland 		&cur_stream->public.timing,
8034562236bSHarry Wentland 		&new_stream->public.timing,
8044562236bSHarry Wentland 		sizeof(struct dc_crtc_timing)) != 0;
8054562236bSHarry Wentland }
8064562236bSHarry Wentland 
8074562236bSHarry Wentland static bool are_stream_backends_same(
8084562236bSHarry Wentland 	const struct core_stream *stream_a, const struct core_stream *stream_b)
8094562236bSHarry Wentland {
8104562236bSHarry Wentland 	if (stream_a == stream_b)
8114562236bSHarry Wentland 		return true;
8124562236bSHarry Wentland 
8134562236bSHarry Wentland 	if (stream_a == NULL || stream_b == NULL)
8144562236bSHarry Wentland 		return false;
8154562236bSHarry Wentland 
8164562236bSHarry Wentland 	if (is_timing_changed(stream_a, stream_b))
8174562236bSHarry Wentland 		return false;
8184562236bSHarry Wentland 
8194562236bSHarry Wentland 	return true;
8204562236bSHarry Wentland }
8214562236bSHarry Wentland 
8224562236bSHarry Wentland bool is_target_unchanged(
8234562236bSHarry Wentland 	const struct core_target *old_target, const struct core_target *target)
8244562236bSHarry Wentland {
8254562236bSHarry Wentland 	int i;
8264562236bSHarry Wentland 
8274562236bSHarry Wentland 	if (old_target == target)
8284562236bSHarry Wentland 		return true;
8294562236bSHarry Wentland 	if (old_target->public.stream_count != target->public.stream_count)
8304562236bSHarry Wentland 		return false;
8314562236bSHarry Wentland 
8324562236bSHarry Wentland 	for (i = 0; i < old_target->public.stream_count; i++) {
8334562236bSHarry Wentland 		const struct core_stream *old_stream = DC_STREAM_TO_CORE(
8344562236bSHarry Wentland 				old_target->public.streams[i]);
8354562236bSHarry Wentland 		const struct core_stream *stream = DC_STREAM_TO_CORE(
8364562236bSHarry Wentland 				target->public.streams[i]);
8374562236bSHarry Wentland 
8384562236bSHarry Wentland 		if (!are_stream_backends_same(old_stream, stream))
8394562236bSHarry Wentland 			return false;
8404562236bSHarry Wentland 	}
8414562236bSHarry Wentland 
8424562236bSHarry Wentland 	return true;
8434562236bSHarry Wentland }
8444562236bSHarry Wentland 
8454562236bSHarry Wentland bool resource_validate_attach_surfaces(
8464562236bSHarry Wentland 		const struct dc_validation_set set[],
8474562236bSHarry Wentland 		int set_count,
8484562236bSHarry Wentland 		const struct validate_context *old_context,
8494562236bSHarry Wentland 		struct validate_context *context)
8504562236bSHarry Wentland {
8514562236bSHarry Wentland 	int i, j;
8524562236bSHarry Wentland 
8534562236bSHarry Wentland 	for (i = 0; i < set_count; i++) {
8544562236bSHarry Wentland 		for (j = 0; j < old_context->target_count; j++)
8554562236bSHarry Wentland 			if (is_target_unchanged(
8564562236bSHarry Wentland 					old_context->targets[j],
8574562236bSHarry Wentland 					context->targets[i])) {
8584562236bSHarry Wentland 				if (!resource_attach_surfaces_to_context(
8594562236bSHarry Wentland 						old_context->target_status[j].surfaces,
8604562236bSHarry Wentland 						old_context->target_status[j].surface_count,
8614562236bSHarry Wentland 						&context->targets[i]->public,
8624562236bSHarry Wentland 						context))
8634562236bSHarry Wentland 					return false;
8644562236bSHarry Wentland 				context->target_status[i] = old_context->target_status[j];
8654562236bSHarry Wentland 			}
8664562236bSHarry Wentland 		if (set[i].surface_count != 0)
8674562236bSHarry Wentland 			if (!resource_attach_surfaces_to_context(
8684562236bSHarry Wentland 					set[i].surfaces,
8694562236bSHarry Wentland 					set[i].surface_count,
8704562236bSHarry Wentland 					&context->targets[i]->public,
8714562236bSHarry Wentland 					context))
8724562236bSHarry Wentland 				return false;
8734562236bSHarry Wentland 
8744562236bSHarry Wentland 	}
8754562236bSHarry Wentland 
8764562236bSHarry Wentland 	return true;
8774562236bSHarry Wentland }
8784562236bSHarry Wentland 
8794562236bSHarry Wentland /* Maximum TMDS single link pixel clock 165MHz */
8804562236bSHarry Wentland #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
8814562236bSHarry Wentland 
8824562236bSHarry Wentland static void set_stream_engine_in_use(
8834562236bSHarry Wentland 		struct resource_context *res_ctx,
8844562236bSHarry Wentland 		struct stream_encoder *stream_enc)
8854562236bSHarry Wentland {
8864562236bSHarry Wentland 	int i;
8874562236bSHarry Wentland 
8884562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
8894562236bSHarry Wentland 		if (res_ctx->pool->stream_enc[i] == stream_enc)
8904562236bSHarry Wentland 			res_ctx->is_stream_enc_acquired[i] = true;
8914562236bSHarry Wentland 	}
8924562236bSHarry Wentland }
8934562236bSHarry Wentland 
8944562236bSHarry Wentland /* TODO: release audio object */
8954562236bSHarry Wentland static void set_audio_in_use(
8964562236bSHarry Wentland 		struct resource_context *res_ctx,
8974562236bSHarry Wentland 		struct audio *audio)
8984562236bSHarry Wentland {
8994562236bSHarry Wentland 	int i;
9004562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->audio_count; i++) {
9014562236bSHarry Wentland 		if (res_ctx->pool->audios[i] == audio) {
9024562236bSHarry Wentland 			res_ctx->is_audio_acquired[i] = true;
9034562236bSHarry Wentland 		}
9044562236bSHarry Wentland 	}
9054562236bSHarry Wentland }
9064562236bSHarry Wentland 
9074562236bSHarry Wentland static int acquire_first_free_pipe(
9084562236bSHarry Wentland 		struct resource_context *res_ctx,
9094562236bSHarry Wentland 		struct core_stream *stream)
9104562236bSHarry Wentland {
9114562236bSHarry Wentland 	int i;
9124562236bSHarry Wentland 
9134562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->pipe_count; i++) {
9144562236bSHarry Wentland 		if (!res_ctx->pipe_ctx[i].stream) {
9154562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
9164562236bSHarry Wentland 
9174562236bSHarry Wentland 			pipe_ctx->tg = res_ctx->pool->timing_generators[i];
9184562236bSHarry Wentland 			pipe_ctx->mi = res_ctx->pool->mis[i];
9194562236bSHarry Wentland 			pipe_ctx->ipp = res_ctx->pool->ipps[i];
9204562236bSHarry Wentland 			pipe_ctx->xfm = res_ctx->pool->transforms[i];
9214562236bSHarry Wentland 			pipe_ctx->opp = res_ctx->pool->opps[i];
9224562236bSHarry Wentland 			pipe_ctx->dis_clk = res_ctx->pool->display_clock;
9234562236bSHarry Wentland 			pipe_ctx->pipe_idx = i;
9244562236bSHarry Wentland 
9254562236bSHarry Wentland 			pipe_ctx->stream = stream;
9264562236bSHarry Wentland 			return i;
9274562236bSHarry Wentland 		}
9284562236bSHarry Wentland 	}
9294562236bSHarry Wentland 	return -1;
9304562236bSHarry Wentland }
9314562236bSHarry Wentland 
9324562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link(
9334562236bSHarry Wentland 		struct resource_context *res_ctx,
9344562236bSHarry Wentland 		struct core_stream *stream)
9354562236bSHarry Wentland {
9364562236bSHarry Wentland 	int i;
9374562236bSHarry Wentland 	int j = -1;
9384562236bSHarry Wentland 	struct core_link *link = stream->sink->link;
9394562236bSHarry Wentland 
9404562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
9414562236bSHarry Wentland 		if (!res_ctx->is_stream_enc_acquired[i] &&
9424562236bSHarry Wentland 					res_ctx->pool->stream_enc[i]) {
9434562236bSHarry Wentland 			/* Store first available for MST second display
9444562236bSHarry Wentland 			 * in daisy chain use case */
9454562236bSHarry Wentland 			j = i;
9464562236bSHarry Wentland 			if (res_ctx->pool->stream_enc[i]->id ==
9474562236bSHarry Wentland 					link->link_enc->preferred_engine)
9484562236bSHarry Wentland 				return res_ctx->pool->stream_enc[i];
9494562236bSHarry Wentland 		}
9504562236bSHarry Wentland 	}
9514562236bSHarry Wentland 
9524562236bSHarry Wentland 	/*
9534562236bSHarry Wentland 	 * below can happen in cases when stream encoder is acquired:
9544562236bSHarry Wentland 	 * 1) for second MST display in chain, so preferred engine already
9554562236bSHarry Wentland 	 * acquired;
9564562236bSHarry Wentland 	 * 2) for another link, which preferred engine already acquired by any
9574562236bSHarry Wentland 	 * MST configuration.
9584562236bSHarry Wentland 	 *
9594562236bSHarry Wentland 	 * If signal is of DP type and preferred engine not found, return last available
9604562236bSHarry Wentland 	 *
9614562236bSHarry Wentland 	 * TODO - This is just a patch up and a generic solution is
9624562236bSHarry Wentland 	 * required for non DP connectors.
9634562236bSHarry Wentland 	 */
9644562236bSHarry Wentland 
9654562236bSHarry Wentland 	if (j >= 0 && dc_is_dp_signal(stream->signal))
9664562236bSHarry Wentland 		return res_ctx->pool->stream_enc[j];
9674562236bSHarry Wentland 
9684562236bSHarry Wentland 	return NULL;
9694562236bSHarry Wentland }
9704562236bSHarry Wentland 
9714562236bSHarry Wentland static struct audio *find_first_free_audio(struct resource_context *res_ctx)
9724562236bSHarry Wentland {
9734562236bSHarry Wentland 	int i;
9744562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->audio_count; i++) {
9754562236bSHarry Wentland 		if (res_ctx->is_audio_acquired[i] == false) {
9764562236bSHarry Wentland 			return res_ctx->pool->audios[i];
9774562236bSHarry Wentland 		}
9784562236bSHarry Wentland 	}
9794562236bSHarry Wentland 
9804562236bSHarry Wentland 	return 0;
9814562236bSHarry Wentland }
9824562236bSHarry Wentland 
9834562236bSHarry Wentland static void update_stream_signal(struct core_stream *stream)
9844562236bSHarry Wentland {
9854562236bSHarry Wentland 	const struct dc_sink *dc_sink = stream->public.sink;
9864562236bSHarry Wentland 
9874562236bSHarry Wentland 	stream->signal = dc_sink->sink_signal;
9884562236bSHarry Wentland 	/* For asic supports dual link DVI, we should adjust signal type
9894562236bSHarry Wentland 	 * based on timing pixel clock. If pixel clock more than 165Mhz,
9904562236bSHarry Wentland 	 * signal is dual link, otherwise, single link.
9914562236bSHarry Wentland 	 */
9924562236bSHarry Wentland 	if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
9934562236bSHarry Wentland 			dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) {
9944562236bSHarry Wentland 		if (stream->public.timing.pix_clk_khz >
9954562236bSHarry Wentland 						TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
9964562236bSHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
9974562236bSHarry Wentland 		else
9984562236bSHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
9994562236bSHarry Wentland 	}
10004562236bSHarry Wentland }
10014562236bSHarry Wentland 
10024562236bSHarry Wentland bool resource_is_stream_unchanged(
10034562236bSHarry Wentland 	const struct validate_context *old_context, struct core_stream *stream)
10044562236bSHarry Wentland {
10054562236bSHarry Wentland 	int i, j;
10064562236bSHarry Wentland 
10074562236bSHarry Wentland 	for (i = 0; i < old_context->target_count; i++) {
10084562236bSHarry Wentland 		struct core_target *old_target = old_context->targets[i];
10094562236bSHarry Wentland 
10104562236bSHarry Wentland 		for (j = 0; j < old_target->public.stream_count; j++) {
10114562236bSHarry Wentland 			struct core_stream *old_stream =
10124562236bSHarry Wentland 				DC_STREAM_TO_CORE(old_target->public.streams[j]);
10134562236bSHarry Wentland 
10144562236bSHarry Wentland 			if (are_stream_backends_same(old_stream, stream))
10154562236bSHarry Wentland 				return true;
10164562236bSHarry Wentland 		}
10174562236bSHarry Wentland 	}
10184562236bSHarry Wentland 
10194562236bSHarry Wentland 	return false;
10204562236bSHarry Wentland }
10214562236bSHarry Wentland 
10224562236bSHarry Wentland static void copy_pipe_ctx(
10234562236bSHarry Wentland 	const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
10244562236bSHarry Wentland {
10254562236bSHarry Wentland 	struct core_surface *surface = to_pipe_ctx->surface;
10264562236bSHarry Wentland 	struct core_stream *stream = to_pipe_ctx->stream;
10274562236bSHarry Wentland 
10284562236bSHarry Wentland 	*to_pipe_ctx = *from_pipe_ctx;
10294562236bSHarry Wentland 	to_pipe_ctx->stream = stream;
10304562236bSHarry Wentland 	if (surface != NULL)
10314562236bSHarry Wentland 		to_pipe_ctx->surface = surface;
10324562236bSHarry Wentland }
10334562236bSHarry Wentland 
10344562236bSHarry Wentland static struct core_stream *find_pll_sharable_stream(
10354562236bSHarry Wentland 		const struct core_stream *stream_needs_pll,
10364562236bSHarry Wentland 		struct validate_context *context)
10374562236bSHarry Wentland {
10384562236bSHarry Wentland 	int i, j;
10394562236bSHarry Wentland 
10404562236bSHarry Wentland 	for (i = 0; i < context->target_count; i++) {
10414562236bSHarry Wentland 		struct core_target *target = context->targets[i];
10424562236bSHarry Wentland 
10434562236bSHarry Wentland 		for (j = 0; j < target->public.stream_count; j++) {
10444562236bSHarry Wentland 			struct core_stream *stream_has_pll =
10454562236bSHarry Wentland 				DC_STREAM_TO_CORE(target->public.streams[j]);
10464562236bSHarry Wentland 
10474562236bSHarry Wentland 			/* We are looking for non dp, non virtual stream */
10484562236bSHarry Wentland 			if (resource_are_streams_timing_synchronizable(
10494562236bSHarry Wentland 						stream_needs_pll, stream_has_pll)
10504562236bSHarry Wentland 				&& !dc_is_dp_signal(stream_has_pll->signal)
10514562236bSHarry Wentland 				&& stream_has_pll->sink->link->public.connector_signal
10524562236bSHarry Wentland 							!= SIGNAL_TYPE_VIRTUAL)
10534562236bSHarry Wentland 					return stream_has_pll;
10544562236bSHarry Wentland 		}
10554562236bSHarry Wentland 	}
10564562236bSHarry Wentland 
10574562236bSHarry Wentland 	return NULL;
10584562236bSHarry Wentland }
10594562236bSHarry Wentland 
10604562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
10614562236bSHarry Wentland {
10624562236bSHarry Wentland 	uint32_t pix_clk = timing->pix_clk_khz;
10634562236bSHarry Wentland 	uint32_t normalized_pix_clk = pix_clk;
10644562236bSHarry Wentland 
10654562236bSHarry Wentland 	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
10664562236bSHarry Wentland 		pix_clk /= 2;
10674562236bSHarry Wentland 
10684562236bSHarry Wentland 	switch (timing->display_color_depth) {
10694562236bSHarry Wentland 	case COLOR_DEPTH_888:
10704562236bSHarry Wentland 		normalized_pix_clk = pix_clk;
10714562236bSHarry Wentland 		break;
10724562236bSHarry Wentland 	case COLOR_DEPTH_101010:
10734562236bSHarry Wentland 		normalized_pix_clk = (pix_clk * 30) / 24;
10744562236bSHarry Wentland 		break;
10754562236bSHarry Wentland 	case COLOR_DEPTH_121212:
10764562236bSHarry Wentland 		normalized_pix_clk = (pix_clk * 36) / 24;
10774562236bSHarry Wentland 		break;
10784562236bSHarry Wentland 	case COLOR_DEPTH_161616:
10794562236bSHarry Wentland 		normalized_pix_clk = (pix_clk * 48) / 24;
10804562236bSHarry Wentland 		break;
10814562236bSHarry Wentland 	default:
10824562236bSHarry Wentland 		ASSERT(0);
10834562236bSHarry Wentland 		break;
10844562236bSHarry Wentland 	}
10854562236bSHarry Wentland 
10864562236bSHarry Wentland 	return normalized_pix_clk;
10874562236bSHarry Wentland }
10884562236bSHarry Wentland 
10894562236bSHarry Wentland static void calculate_phy_pix_clks(
10904562236bSHarry Wentland 		const struct core_dc *dc,
10914562236bSHarry Wentland 		struct validate_context *context)
10924562236bSHarry Wentland {
10934562236bSHarry Wentland 	int i, j;
10944562236bSHarry Wentland 
10954562236bSHarry Wentland 	for (i = 0; i < context->target_count; i++) {
10964562236bSHarry Wentland 		struct core_target *target = context->targets[i];
10974562236bSHarry Wentland 
10984562236bSHarry Wentland 		for (j = 0; j < target->public.stream_count; j++) {
10994562236bSHarry Wentland 			struct core_stream *stream =
11004562236bSHarry Wentland 				DC_STREAM_TO_CORE(target->public.streams[j]);
11014562236bSHarry Wentland 
11024562236bSHarry Wentland 			update_stream_signal(stream);
11034562236bSHarry Wentland 
11044562236bSHarry Wentland 			/* update actual pixel clock on all streams */
11054562236bSHarry Wentland 			if (dc_is_hdmi_signal(stream->signal))
11064562236bSHarry Wentland 				stream->phy_pix_clk = get_norm_pix_clk(
11074562236bSHarry Wentland 					&stream->public.timing);
11084562236bSHarry Wentland 			else
11094562236bSHarry Wentland 				stream->phy_pix_clk =
11104562236bSHarry Wentland 						stream->public.timing.pix_clk_khz;
11114562236bSHarry Wentland 		}
11124562236bSHarry Wentland 	}
11134562236bSHarry Wentland }
11144562236bSHarry Wentland 
11154562236bSHarry Wentland enum dc_status resource_map_pool_resources(
11164562236bSHarry Wentland 		const struct core_dc *dc,
11174562236bSHarry Wentland 		struct validate_context *context)
11184562236bSHarry Wentland {
11194562236bSHarry Wentland 	int i, j, k;
11204562236bSHarry Wentland 
11214562236bSHarry Wentland 	calculate_phy_pix_clks(dc, context);
11224562236bSHarry Wentland 
11234562236bSHarry Wentland 	for (i = 0; i < context->target_count; i++) {
11244562236bSHarry Wentland 		struct core_target *target = context->targets[i];
11254562236bSHarry Wentland 
11264562236bSHarry Wentland 		for (j = 0; j < target->public.stream_count; j++) {
11274562236bSHarry Wentland 			struct core_stream *stream =
11284562236bSHarry Wentland 				DC_STREAM_TO_CORE(target->public.streams[j]);
11294562236bSHarry Wentland 
11304562236bSHarry Wentland 			if (!resource_is_stream_unchanged(dc->current_context, stream))
11314562236bSHarry Wentland 				continue;
11324562236bSHarry Wentland 
11334562236bSHarry Wentland 			/* mark resources used for stream that is already active */
11344562236bSHarry Wentland 			for (k = 0; k < MAX_PIPES; k++) {
11354562236bSHarry Wentland 				struct pipe_ctx *pipe_ctx =
11364562236bSHarry Wentland 					&context->res_ctx.pipe_ctx[k];
11374562236bSHarry Wentland 				const struct pipe_ctx *old_pipe_ctx =
11384562236bSHarry Wentland 					&dc->current_context->res_ctx.pipe_ctx[k];
11394562236bSHarry Wentland 
11404562236bSHarry Wentland 				if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
11414562236bSHarry Wentland 					continue;
11424562236bSHarry Wentland 
11434562236bSHarry Wentland 				pipe_ctx->stream = stream;
11444562236bSHarry Wentland 				copy_pipe_ctx(old_pipe_ctx, pipe_ctx);
11454562236bSHarry Wentland 
11468c737fccSYongqiang Sun 				/* Split pipe resource, do not acquire back end */
11478c737fccSYongqiang Sun 				if (!pipe_ctx->stream_enc)
11488c737fccSYongqiang Sun 					continue;
11498c737fccSYongqiang Sun 
11504562236bSHarry Wentland 				set_stream_engine_in_use(
11514562236bSHarry Wentland 					&context->res_ctx,
11524562236bSHarry Wentland 					pipe_ctx->stream_enc);
11534562236bSHarry Wentland 
11544562236bSHarry Wentland 				/* Switch to dp clock source only if there is
11554562236bSHarry Wentland 				 * no non dp stream that shares the same timing
11564562236bSHarry Wentland 				 * with the dp stream.
11574562236bSHarry Wentland 				 */
11584562236bSHarry Wentland 				if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
11594562236bSHarry Wentland 					!find_pll_sharable_stream(stream, context))
11604562236bSHarry Wentland 					pipe_ctx->clock_source =
11614562236bSHarry Wentland 						context->res_ctx.pool->dp_clock_source;
11624562236bSHarry Wentland 
11634562236bSHarry Wentland 				resource_reference_clock_source(
11644562236bSHarry Wentland 					&context->res_ctx,
11654562236bSHarry Wentland 					pipe_ctx->clock_source);
11664562236bSHarry Wentland 
11674562236bSHarry Wentland 				set_audio_in_use(&context->res_ctx,
11684562236bSHarry Wentland 					pipe_ctx->audio);
11694562236bSHarry Wentland 			}
11704562236bSHarry Wentland 		}
11714562236bSHarry Wentland 	}
11724562236bSHarry Wentland 
11734562236bSHarry Wentland 	for (i = 0; i < context->target_count; i++) {
11744562236bSHarry Wentland 		struct core_target *target = context->targets[i];
11754562236bSHarry Wentland 
11764562236bSHarry Wentland 		for (j = 0; j < target->public.stream_count; j++) {
11774562236bSHarry Wentland 			struct core_stream *stream =
11784562236bSHarry Wentland 				DC_STREAM_TO_CORE(target->public.streams[j]);
11794562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx = NULL;
11804562236bSHarry Wentland 			int pipe_idx = -1;
11814562236bSHarry Wentland 
11824562236bSHarry Wentland 			if (resource_is_stream_unchanged(dc->current_context, stream))
11834562236bSHarry Wentland 				continue;
11844562236bSHarry Wentland 			/* acquire new resources */
11854562236bSHarry Wentland 			pipe_idx = acquire_first_free_pipe(
11864562236bSHarry Wentland 						&context->res_ctx, stream);
11874562236bSHarry Wentland 			if (pipe_idx < 0)
11884562236bSHarry Wentland 				return DC_NO_CONTROLLER_RESOURCE;
11894562236bSHarry Wentland 
11904562236bSHarry Wentland 
11914562236bSHarry Wentland 			pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
11924562236bSHarry Wentland 
11934562236bSHarry Wentland 			pipe_ctx->stream_enc =
11944562236bSHarry Wentland 				find_first_free_match_stream_enc_for_link(
11954562236bSHarry Wentland 					&context->res_ctx, stream);
11964562236bSHarry Wentland 
11974562236bSHarry Wentland 			if (!pipe_ctx->stream_enc)
11984562236bSHarry Wentland 				return DC_NO_STREAM_ENG_RESOURCE;
11994562236bSHarry Wentland 
12004562236bSHarry Wentland 			set_stream_engine_in_use(
12014562236bSHarry Wentland 					&context->res_ctx,
12024562236bSHarry Wentland 					pipe_ctx->stream_enc);
12034562236bSHarry Wentland 
12044562236bSHarry Wentland 			/* TODO: Add check if ASIC support and EDID audio */
12054562236bSHarry Wentland 			if (!stream->sink->converter_disable_audio &&
12064562236bSHarry Wentland 						dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
12074562236bSHarry Wentland 						stream->public.audio_info.mode_count) {
12084562236bSHarry Wentland 				pipe_ctx->audio = find_first_free_audio(
12094562236bSHarry Wentland 						&context->res_ctx);
12104562236bSHarry Wentland 
12114562236bSHarry Wentland 				/*
12124562236bSHarry Wentland 				 * Audio assigned in order first come first get.
12134562236bSHarry Wentland 				 * There are asics which has number of audio
12144562236bSHarry Wentland 				 * resources less then number of pipes
12154562236bSHarry Wentland 				 */
12164562236bSHarry Wentland 				if (pipe_ctx->audio)
12174562236bSHarry Wentland 					set_audio_in_use(
12184562236bSHarry Wentland 						&context->res_ctx,
12194562236bSHarry Wentland 						pipe_ctx->audio);
12204562236bSHarry Wentland 			}
12214562236bSHarry Wentland 
12224562236bSHarry Wentland 			if (j == 0) {
12234562236bSHarry Wentland 				context->target_status[i].primary_otg_inst =
12244562236bSHarry Wentland 						pipe_ctx->tg->inst;
12254562236bSHarry Wentland 			}
12264562236bSHarry Wentland 		}
12274562236bSHarry Wentland 	}
12284562236bSHarry Wentland 
12294562236bSHarry Wentland 	return DC_OK;
12304562236bSHarry Wentland }
12314562236bSHarry Wentland 
12324562236bSHarry Wentland /* first target in the context is used to populate the rest */
12334562236bSHarry Wentland void validate_guaranteed_copy_target(
12344562236bSHarry Wentland 		struct validate_context *context,
12354562236bSHarry Wentland 		int max_targets)
12364562236bSHarry Wentland {
12374562236bSHarry Wentland 	int i;
12384562236bSHarry Wentland 
12394562236bSHarry Wentland 	for (i = 1; i < max_targets; i++) {
12404562236bSHarry Wentland 		context->targets[i] = context->targets[0];
12414562236bSHarry Wentland 
12424562236bSHarry Wentland 		copy_pipe_ctx(&context->res_ctx.pipe_ctx[0],
12434562236bSHarry Wentland 			      &context->res_ctx.pipe_ctx[i]);
12444562236bSHarry Wentland 		context->res_ctx.pipe_ctx[i].stream =
12454562236bSHarry Wentland 				context->res_ctx.pipe_ctx[0].stream;
12464562236bSHarry Wentland 
12474562236bSHarry Wentland 		dc_target_retain(&context->targets[i]->public);
12484562236bSHarry Wentland 		context->target_count++;
12494562236bSHarry Wentland 	}
12504562236bSHarry Wentland }
12514562236bSHarry Wentland 
12524562236bSHarry Wentland static void translate_info_frame(const struct hw_info_frame *hw_info_frame,
12534562236bSHarry Wentland 	struct encoder_info_frame *encoder_info_frame)
12544562236bSHarry Wentland {
12554562236bSHarry Wentland 	memset(
12564562236bSHarry Wentland 		encoder_info_frame, 0, sizeof(struct encoder_info_frame));
12574562236bSHarry Wentland 
12584562236bSHarry Wentland 	/* For gamut we recalc checksum */
12594562236bSHarry Wentland 	if (hw_info_frame->gamut_packet.valid) {
12604562236bSHarry Wentland 		uint8_t chk_sum = 0;
12614562236bSHarry Wentland 		uint8_t *ptr;
12624562236bSHarry Wentland 		uint8_t i;
12634562236bSHarry Wentland 
12644562236bSHarry Wentland 		memmove(
12654562236bSHarry Wentland 						&encoder_info_frame->gamut,
12664562236bSHarry Wentland 						&hw_info_frame->gamut_packet,
12674562236bSHarry Wentland 						sizeof(struct hw_info_packet));
12684562236bSHarry Wentland 
12694562236bSHarry Wentland 		/*start of the Gamut data. */
12704562236bSHarry Wentland 		ptr = &encoder_info_frame->gamut.sb[3];
12714562236bSHarry Wentland 
12724562236bSHarry Wentland 		for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++)
12734562236bSHarry Wentland 			chk_sum += ptr[i];
12744562236bSHarry Wentland 
12754562236bSHarry Wentland 		encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum);
12764562236bSHarry Wentland 	}
12774562236bSHarry Wentland 
12784562236bSHarry Wentland 	if (hw_info_frame->avi_info_packet.valid) {
12794562236bSHarry Wentland 		memmove(
12804562236bSHarry Wentland 						&encoder_info_frame->avi,
12814562236bSHarry Wentland 						&hw_info_frame->avi_info_packet,
12824562236bSHarry Wentland 						sizeof(struct hw_info_packet));
12834562236bSHarry Wentland 	}
12844562236bSHarry Wentland 
12854562236bSHarry Wentland 	if (hw_info_frame->vendor_info_packet.valid) {
12864562236bSHarry Wentland 		memmove(
12874562236bSHarry Wentland 						&encoder_info_frame->vendor,
12884562236bSHarry Wentland 						&hw_info_frame->vendor_info_packet,
12894562236bSHarry Wentland 						sizeof(struct hw_info_packet));
12904562236bSHarry Wentland 	}
12914562236bSHarry Wentland 
12924562236bSHarry Wentland 	if (hw_info_frame->spd_packet.valid) {
12934562236bSHarry Wentland 		memmove(
12944562236bSHarry Wentland 						&encoder_info_frame->spd,
12954562236bSHarry Wentland 						&hw_info_frame->spd_packet,
12964562236bSHarry Wentland 						sizeof(struct hw_info_packet));
12974562236bSHarry Wentland 	}
12984562236bSHarry Wentland 
12994562236bSHarry Wentland 	if (hw_info_frame->vsc_packet.valid) {
13004562236bSHarry Wentland 		memmove(
13014562236bSHarry Wentland 						&encoder_info_frame->vsc,
13024562236bSHarry Wentland 						&hw_info_frame->vsc_packet,
13034562236bSHarry Wentland 						sizeof(struct hw_info_packet));
13044562236bSHarry Wentland 	}
13051646a6feSAndrew Wong 
13061646a6feSAndrew Wong 	if (hw_info_frame->hdrsmd_packet.valid) {
13071646a6feSAndrew Wong 		memmove(
13081646a6feSAndrew Wong 						&encoder_info_frame->hdrsmd,
13091646a6feSAndrew Wong 						&hw_info_frame->hdrsmd_packet,
13101646a6feSAndrew Wong 						sizeof(struct hw_info_packet));
13111646a6feSAndrew Wong 	}
13124562236bSHarry Wentland }
13134562236bSHarry Wentland 
13144562236bSHarry Wentland static void set_avi_info_frame(
13154562236bSHarry Wentland 	struct hw_info_packet *info_packet,
13164562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
13174562236bSHarry Wentland {
13184562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
13194562236bSHarry Wentland 	enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
13204562236bSHarry Wentland 	struct info_frame info_frame = { {0} };
13214562236bSHarry Wentland 	uint32_t pixel_encoding = 0;
13224562236bSHarry Wentland 	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
13234562236bSHarry Wentland 	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
13244562236bSHarry Wentland 	bool itc = false;
13254562236bSHarry Wentland 	uint8_t cn0_cn1 = 0;
13264562236bSHarry Wentland 	uint8_t *check_sum = NULL;
13274562236bSHarry Wentland 	uint8_t byte_index = 0;
13284562236bSHarry Wentland 
13294562236bSHarry Wentland 	if (info_packet == NULL)
13304562236bSHarry Wentland 		return;
13314562236bSHarry Wentland 
13324562236bSHarry Wentland 	color_space = pipe_ctx->stream->public.output_color_space;
13334562236bSHarry Wentland 
13344562236bSHarry Wentland 	/* Initialize header */
13354562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.
13364562236bSHarry Wentland 			info_frame_type = INFO_FRAME_AVI;
13374562236bSHarry Wentland 	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
13384562236bSHarry Wentland 	* not be used in HDMI 2.0 (Section 10.1) */
13394562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.version =
13404562236bSHarry Wentland 			INFO_FRAME_VERSION_2;
13414562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.length =
13424562236bSHarry Wentland 			INFO_FRAME_SIZE_AVI;
13434562236bSHarry Wentland 
13444562236bSHarry Wentland 	/*
13454562236bSHarry Wentland 	 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
13464562236bSHarry Wentland 	 * according to HDMI 2.0 spec (Section 10.1)
13474562236bSHarry Wentland 	 */
13484562236bSHarry Wentland 
13494562236bSHarry Wentland 	switch (stream->public.timing.pixel_encoding) {
13504562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR422:
13514562236bSHarry Wentland 		pixel_encoding = 1;
13524562236bSHarry Wentland 		break;
13534562236bSHarry Wentland 
13544562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR444:
13554562236bSHarry Wentland 		pixel_encoding = 2;
13564562236bSHarry Wentland 		break;
13574562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR420:
13584562236bSHarry Wentland 		pixel_encoding = 3;
13594562236bSHarry Wentland 		break;
13604562236bSHarry Wentland 
13614562236bSHarry Wentland 	case PIXEL_ENCODING_RGB:
13624562236bSHarry Wentland 	default:
13634562236bSHarry Wentland 		pixel_encoding = 0;
13644562236bSHarry Wentland 	}
13654562236bSHarry Wentland 
13664562236bSHarry Wentland 	/* Y0_Y1_Y2 : The pixel encoding */
13674562236bSHarry Wentland 	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
13684562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 =
13694562236bSHarry Wentland 		pixel_encoding;
13704562236bSHarry Wentland 
13714562236bSHarry Wentland 	/* A0 = 1 Active Format Information valid */
13724562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.A0 =
13734562236bSHarry Wentland 		ACTIVE_FORMAT_VALID;
13744562236bSHarry Wentland 
13754562236bSHarry Wentland 	/* B0, B1 = 3; Bar info data is valid */
13764562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 =
13774562236bSHarry Wentland 		BAR_INFO_BOTH_VALID;
13784562236bSHarry Wentland 
13794562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 =
13804562236bSHarry Wentland 			PICTURE_SCALING_UNIFORM;
13814562236bSHarry Wentland 
13824562236bSHarry Wentland 	/* S0, S1 : Underscan / Overscan */
13834562236bSHarry Wentland 	/* TODO: un-hardcode scan type */
13844562236bSHarry Wentland 	scan_type = SCANNING_TYPE_UNDERSCAN;
13854562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type;
13864562236bSHarry Wentland 
13874562236bSHarry Wentland 	/* C0, C1 : Colorimetry */
13884562236bSHarry Wentland 	if (color_space == COLOR_SPACE_YCBCR709)
13894562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13904562236bSHarry Wentland 				COLORIMETRY_ITU709;
13914562236bSHarry Wentland 	else if (color_space == COLOR_SPACE_YCBCR601)
13924562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13934562236bSHarry Wentland 				COLORIMETRY_ITU601;
13944562236bSHarry Wentland 	else
13954562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13964562236bSHarry Wentland 				COLORIMETRY_NO_DATA;
13974562236bSHarry Wentland 
13984562236bSHarry Wentland 	/* TODO: un-hardcode aspect ratio */
13994562236bSHarry Wentland 	aspect = stream->public.timing.aspect_ratio;
14004562236bSHarry Wentland 
14014562236bSHarry Wentland 	switch (aspect) {
14024562236bSHarry Wentland 	case ASPECT_RATIO_4_3:
14034562236bSHarry Wentland 	case ASPECT_RATIO_16_9:
14044562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect;
14054562236bSHarry Wentland 		break;
14064562236bSHarry Wentland 
14074562236bSHarry Wentland 	case ASPECT_RATIO_NO_DATA:
14084562236bSHarry Wentland 	case ASPECT_RATIO_64_27:
14094562236bSHarry Wentland 	case ASPECT_RATIO_256_135:
14104562236bSHarry Wentland 	default:
14114562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0;
14124562236bSHarry Wentland 	}
14134562236bSHarry Wentland 
14144562236bSHarry Wentland 	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
14154562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 =
14164562236bSHarry Wentland 			ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
14174562236bSHarry Wentland 
14184562236bSHarry Wentland 	/* TODO: un-hardcode cn0_cn1 and itc */
14194562236bSHarry Wentland 	cn0_cn1 = 0;
14204562236bSHarry Wentland 	itc = false;
14214562236bSHarry Wentland 
14224562236bSHarry Wentland 	if (itc) {
14234562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1;
14244562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 =
14254562236bSHarry Wentland 			cn0_cn1;
14264562236bSHarry Wentland 	}
14274562236bSHarry Wentland 
14284562236bSHarry Wentland 	/* TODO : We should handle YCC quantization */
14294562236bSHarry Wentland 	/* but we do not have matrix calculation */
14304562236bSHarry Wentland 	if (color_space == COLOR_SPACE_SRGB) {
14314562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
14324562236bSHarry Wentland 						RGB_QUANTIZATION_FULL_RANGE;
14334562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
14344562236bSHarry Wentland 						YYC_QUANTIZATION_FULL_RANGE;
14354562236bSHarry Wentland 	} else if (color_space == COLOR_SPACE_SRGB_LIMITED) {
14364562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
14374562236bSHarry Wentland 						RGB_QUANTIZATION_LIMITED_RANGE;
14384562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
14394562236bSHarry Wentland 						YYC_QUANTIZATION_LIMITED_RANGE;
14404562236bSHarry Wentland 	} else {
14414562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
14424562236bSHarry Wentland 						RGB_QUANTIZATION_DEFAULT_RANGE;
14434562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
14444562236bSHarry Wentland 						YYC_QUANTIZATION_LIMITED_RANGE;
14454562236bSHarry Wentland 	}
14464562236bSHarry Wentland 
14474562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 =
14484562236bSHarry Wentland 					stream->public.timing.vic;
14494562236bSHarry Wentland 
14504562236bSHarry Wentland 	/* pixel repetition
14514562236bSHarry Wentland 	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
14524562236bSHarry Wentland 	 * repetition start from 1 */
14534562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0;
14544562236bSHarry Wentland 
14554562236bSHarry Wentland 	/* Bar Info
14564562236bSHarry Wentland 	 * barTop:    Line Number of End of Top Bar.
14574562236bSHarry Wentland 	 * barBottom: Line Number of Start of Bottom Bar.
14584562236bSHarry Wentland 	 * barLeft:   Pixel Number of End of Left Bar.
14594562236bSHarry Wentland 	 * barRight:  Pixel Number of Start of Right Bar. */
14604562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top =
14614562236bSHarry Wentland 			stream->public.timing.v_border_top;
14624562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom =
14634562236bSHarry Wentland 		(stream->public.timing.v_border_top
14644562236bSHarry Wentland 			- stream->public.timing.v_border_bottom + 1);
14654562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left =
14664562236bSHarry Wentland 			stream->public.timing.h_border_left;
14674562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right =
14684562236bSHarry Wentland 		(stream->public.timing.h_total
14694562236bSHarry Wentland 			- stream->public.timing.h_border_right + 1);
14704562236bSHarry Wentland 
14714562236bSHarry Wentland 	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
14724562236bSHarry Wentland 	check_sum =
14734562236bSHarry Wentland 		&info_frame.
14744562236bSHarry Wentland 		avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
14754562236bSHarry Wentland 	*check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI
14764562236bSHarry Wentland 			+ INFO_FRAME_VERSION_2;
14774562236bSHarry Wentland 
14784562236bSHarry Wentland 	for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++)
14794562236bSHarry Wentland 		*check_sum += info_frame.avi_info_packet.info_packet_hdmi.
14804562236bSHarry Wentland 				packet_raw_data.sb[byte_index];
14814562236bSHarry Wentland 
14824562236bSHarry Wentland 	/* one byte complement */
14834562236bSHarry Wentland 	*check_sum = (uint8_t) (0x100 - *check_sum);
14844562236bSHarry Wentland 
14854562236bSHarry Wentland 	/* Store in hw_path_mode */
14864562236bSHarry Wentland 	info_packet->hb0 =
14874562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0;
14884562236bSHarry Wentland 	info_packet->hb1 =
14894562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1;
14904562236bSHarry Wentland 	info_packet->hb2 =
14914562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2;
14924562236bSHarry Wentland 
1493e66e4d64SHarry Wentland 	for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet.
1494e66e4d64SHarry Wentland 				info_packet_hdmi.packet_raw_data.sb); byte_index++)
14954562236bSHarry Wentland 		info_packet->sb[byte_index] = info_frame.avi_info_packet.
14964562236bSHarry Wentland 				info_packet_hdmi.packet_raw_data.sb[byte_index];
14974562236bSHarry Wentland 
14984562236bSHarry Wentland 	info_packet->valid = true;
14994562236bSHarry Wentland }
15004562236bSHarry Wentland 
15014562236bSHarry Wentland static void set_vendor_info_packet(struct core_stream *stream,
15024562236bSHarry Wentland 		struct hw_info_packet *info_packet)
15034562236bSHarry Wentland {
15044562236bSHarry Wentland 	uint32_t length = 0;
15054562236bSHarry Wentland 	bool hdmi_vic_mode = false;
15064562236bSHarry Wentland 	uint8_t checksum = 0;
15074562236bSHarry Wentland 	uint32_t i = 0;
15084562236bSHarry Wentland 	enum dc_timing_3d_format format;
15094562236bSHarry Wentland 
15104562236bSHarry Wentland 	ASSERT_CRITICAL(stream != NULL);
15114562236bSHarry Wentland 	ASSERT_CRITICAL(info_packet != NULL);
15124562236bSHarry Wentland 
15134562236bSHarry Wentland 	format = stream->public.timing.timing_3d_format;
15144562236bSHarry Wentland 
15154562236bSHarry Wentland 	/* Can be different depending on packet content */
15164562236bSHarry Wentland 	length = 5;
15174562236bSHarry Wentland 
15184562236bSHarry Wentland 	if (stream->public.timing.hdmi_vic != 0
15194562236bSHarry Wentland 			&& stream->public.timing.h_total >= 3840
15204562236bSHarry Wentland 			&& stream->public.timing.v_total >= 2160)
15214562236bSHarry Wentland 		hdmi_vic_mode = true;
15224562236bSHarry Wentland 
15234562236bSHarry Wentland 	/* According to HDMI 1.4a CTS, VSIF should be sent
15244562236bSHarry Wentland 	 * for both 3D stereo and HDMI VIC modes.
15254562236bSHarry Wentland 	 * For all other modes, there is no VSIF sent.  */
15264562236bSHarry Wentland 
15274562236bSHarry Wentland 	if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
15284562236bSHarry Wentland 		return;
15294562236bSHarry Wentland 
15304562236bSHarry Wentland 	/* 24bit IEEE Registration identifier (0x000c03). LSB first. */
15314562236bSHarry Wentland 	info_packet->sb[1] = 0x03;
15324562236bSHarry Wentland 	info_packet->sb[2] = 0x0C;
15334562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
15344562236bSHarry Wentland 
15354562236bSHarry Wentland 	/*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
15364562236bSHarry Wentland 	 * The value for HDMI_Video_Format are:
15374562236bSHarry Wentland 	 * 0x0 (0b000) - No additional HDMI video format is presented in this
15384562236bSHarry Wentland 	 * packet
15394562236bSHarry Wentland 	 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
15404562236bSHarry Wentland 	 * parameter follows
15414562236bSHarry Wentland 	 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
15424562236bSHarry Wentland 	 * potentially 3D_Ext_Data follows
15434562236bSHarry Wentland 	 * 0x3..0x7 (0b011..0b111) - reserved for future use */
15444562236bSHarry Wentland 	if (format != TIMING_3D_FORMAT_NONE)
15454562236bSHarry Wentland 		info_packet->sb[4] = (2 << 5);
15464562236bSHarry Wentland 	else if (hdmi_vic_mode)
15474562236bSHarry Wentland 		info_packet->sb[4] = (1 << 5);
15484562236bSHarry Wentland 
15494562236bSHarry Wentland 	/* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
15504562236bSHarry Wentland 	 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
15514562236bSHarry Wentland 	 * The value for 3D_Structure are:
15524562236bSHarry Wentland 	 * 0x0 - Frame Packing
15534562236bSHarry Wentland 	 * 0x1 - Field Alternative
15544562236bSHarry Wentland 	 * 0x2 - Line Alternative
15554562236bSHarry Wentland 	 * 0x3 - Side-by-Side (full)
15564562236bSHarry Wentland 	 * 0x4 - L + depth
15574562236bSHarry Wentland 	 * 0x5 - L + depth + graphics + graphics-depth
15584562236bSHarry Wentland 	 * 0x6 - Top-and-Bottom
15594562236bSHarry Wentland 	 * 0x7 - Reserved for future use
15604562236bSHarry Wentland 	 * 0x8 - Side-by-Side (Half)
15614562236bSHarry Wentland 	 * 0x9..0xE - Reserved for future use
15624562236bSHarry Wentland 	 * 0xF - Not used */
15634562236bSHarry Wentland 	switch (format) {
15644562236bSHarry Wentland 	case TIMING_3D_FORMAT_HW_FRAME_PACKING:
15654562236bSHarry Wentland 	case TIMING_3D_FORMAT_SW_FRAME_PACKING:
15664562236bSHarry Wentland 		info_packet->sb[5] = (0x0 << 4);
15674562236bSHarry Wentland 		break;
15684562236bSHarry Wentland 
15694562236bSHarry Wentland 	case TIMING_3D_FORMAT_SIDE_BY_SIDE:
15704562236bSHarry Wentland 	case TIMING_3D_FORMAT_SBS_SW_PACKED:
15714562236bSHarry Wentland 		info_packet->sb[5] = (0x8 << 4);
15724562236bSHarry Wentland 		length = 6;
15734562236bSHarry Wentland 		break;
15744562236bSHarry Wentland 
15754562236bSHarry Wentland 	case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
15764562236bSHarry Wentland 	case TIMING_3D_FORMAT_TB_SW_PACKED:
15774562236bSHarry Wentland 		info_packet->sb[5] = (0x6 << 4);
15784562236bSHarry Wentland 		break;
15794562236bSHarry Wentland 
15804562236bSHarry Wentland 	default:
15814562236bSHarry Wentland 		break;
15824562236bSHarry Wentland 	}
15834562236bSHarry Wentland 
15844562236bSHarry Wentland 	/*PB5: If PB4 is set to 0x1 (extended resolution format)
15854562236bSHarry Wentland 	 * fill PB5 with the correct HDMI VIC code */
15864562236bSHarry Wentland 	if (hdmi_vic_mode)
15874562236bSHarry Wentland 		info_packet->sb[5] = stream->public.timing.hdmi_vic;
15884562236bSHarry Wentland 
15894562236bSHarry Wentland 	/* Header */
15904562236bSHarry Wentland 	info_packet->hb0 = 0x81; /* VSIF packet type. */
15914562236bSHarry Wentland 	info_packet->hb1 = 0x01; /* Version */
15924562236bSHarry Wentland 
15934562236bSHarry Wentland 	/* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
15944562236bSHarry Wentland 	info_packet->hb2 = (uint8_t) (length);
15954562236bSHarry Wentland 
15964562236bSHarry Wentland 	/* Calculate checksum */
15974562236bSHarry Wentland 	checksum = 0;
15984562236bSHarry Wentland 	checksum += info_packet->hb0;
15994562236bSHarry Wentland 	checksum += info_packet->hb1;
16004562236bSHarry Wentland 	checksum += info_packet->hb2;
16014562236bSHarry Wentland 
16024562236bSHarry Wentland 	for (i = 1; i <= length; i++)
16034562236bSHarry Wentland 		checksum += info_packet->sb[i];
16044562236bSHarry Wentland 
16054562236bSHarry Wentland 	info_packet->sb[0] = (uint8_t) (0x100 - checksum);
16064562236bSHarry Wentland 
16074562236bSHarry Wentland 	info_packet->valid = true;
16084562236bSHarry Wentland }
16094562236bSHarry Wentland 
16104562236bSHarry Wentland static void set_spd_info_packet(struct core_stream *stream,
16114562236bSHarry Wentland 		struct hw_info_packet *info_packet)
16124562236bSHarry Wentland {
16134562236bSHarry Wentland 	/* SPD info packet for FreeSync */
16144562236bSHarry Wentland 
16154562236bSHarry Wentland 	unsigned char checksum = 0;
16164562236bSHarry Wentland 	unsigned int idx, payload_size = 0;
16174562236bSHarry Wentland 
16184562236bSHarry Wentland 	/* Check if Freesync is supported. Return if false. If true,
16194562236bSHarry Wentland 	 * set the corresponding bit in the info packet
16204562236bSHarry Wentland 	 */
16214562236bSHarry Wentland 	if (stream->public.freesync_ctx.supported == false)
16224562236bSHarry Wentland 		return;
16234562236bSHarry Wentland 
16244562236bSHarry Wentland 	if (dc_is_hdmi_signal(stream->signal)) {
16254562236bSHarry Wentland 
16264562236bSHarry Wentland 		/* HEADER */
16274562236bSHarry Wentland 
16284562236bSHarry Wentland 		/* HB0  = Packet Type = 0x83 (Source Product
16294562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
16304562236bSHarry Wentland 		 */
16314562236bSHarry Wentland 		info_packet->hb0 = 0x83;
16324562236bSHarry Wentland 
16334562236bSHarry Wentland 		/* HB1  = Version = 0x01 */
16344562236bSHarry Wentland 		info_packet->hb1 = 0x01;
16354562236bSHarry Wentland 
16364562236bSHarry Wentland 		/* HB2  = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
16374562236bSHarry Wentland 		info_packet->hb2 = 0x08;
16384562236bSHarry Wentland 
16394562236bSHarry Wentland 		payload_size = 0x08;
16404562236bSHarry Wentland 
16414562236bSHarry Wentland 	} else if (dc_is_dp_signal(stream->signal)) {
16424562236bSHarry Wentland 
16434562236bSHarry Wentland 		/* HEADER */
16444562236bSHarry Wentland 
16454562236bSHarry Wentland 		/* HB0  = Secondary-data Packet ID = 0 - Only non-zero
16464562236bSHarry Wentland 		 *	  when used to associate audio related info packets
16474562236bSHarry Wentland 		 */
16484562236bSHarry Wentland 		info_packet->hb0 = 0x00;
16494562236bSHarry Wentland 
16504562236bSHarry Wentland 		/* HB1  = Packet Type = 0x83 (Source Product
16514562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
16524562236bSHarry Wentland 		 */
16534562236bSHarry Wentland 		info_packet->hb1 = 0x83;
16544562236bSHarry Wentland 
16554562236bSHarry Wentland 		/* HB2  = [Bits 7:0 = Least significant eight bits -
16564562236bSHarry Wentland 		 *	  For INFOFRAME, the value must be 1Bh]
16574562236bSHarry Wentland 		 */
16584562236bSHarry Wentland 		info_packet->hb2 = 0x1B;
16594562236bSHarry Wentland 
16604562236bSHarry Wentland 		/* HB3  = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
16614562236bSHarry Wentland 		 *	  [Bits 1:0 = Most significant two bits = 0x00]
16624562236bSHarry Wentland 		 */
16634562236bSHarry Wentland 		info_packet->hb3 = 0x04;
16644562236bSHarry Wentland 
16654562236bSHarry Wentland 		payload_size = 0x1B;
16664562236bSHarry Wentland 	}
16674562236bSHarry Wentland 
16684562236bSHarry Wentland 	/* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
16694562236bSHarry Wentland 	info_packet->sb[1] = 0x1A;
16704562236bSHarry Wentland 
16714562236bSHarry Wentland 	/* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
16724562236bSHarry Wentland 	info_packet->sb[2] = 0x00;
16734562236bSHarry Wentland 
16744562236bSHarry Wentland 	/* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
16754562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
16764562236bSHarry Wentland 
16774562236bSHarry Wentland 	/* PB4 = Reserved */
16784562236bSHarry Wentland 	info_packet->sb[4] = 0x00;
16794562236bSHarry Wentland 
16804562236bSHarry Wentland 	/* PB5 = Reserved */
16814562236bSHarry Wentland 	info_packet->sb[5] = 0x00;
16824562236bSHarry Wentland 
16834562236bSHarry Wentland 	/* PB6 = [Bits 7:3 = Reserved] */
16844562236bSHarry Wentland 	info_packet->sb[6] = 0x00;
16854562236bSHarry Wentland 
16864562236bSHarry Wentland 	if (stream->public.freesync_ctx.supported == true)
16874562236bSHarry Wentland 		/* PB6 = [Bit 0 = FreeSync Supported] */
16884562236bSHarry Wentland 		info_packet->sb[6] |= 0x01;
16894562236bSHarry Wentland 
16904562236bSHarry Wentland 	if (stream->public.freesync_ctx.enabled == true)
16914562236bSHarry Wentland 		/* PB6 = [Bit 1 = FreeSync Enabled] */
16924562236bSHarry Wentland 		info_packet->sb[6] |= 0x02;
16934562236bSHarry Wentland 
16944562236bSHarry Wentland 	if (stream->public.freesync_ctx.active == true)
16954562236bSHarry Wentland 		/* PB6 = [Bit 2 = FreeSync Active] */
16964562236bSHarry Wentland 		info_packet->sb[6] |= 0x04;
16974562236bSHarry Wentland 
16984562236bSHarry Wentland 	/* PB7 = FreeSync Minimum refresh rate (Hz) */
16994562236bSHarry Wentland 	info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx.
17004562236bSHarry Wentland 			min_refresh_in_micro_hz / 1000000);
17014562236bSHarry Wentland 
17024562236bSHarry Wentland 	/* PB8 = FreeSync Maximum refresh rate (Hz)
17034562236bSHarry Wentland 	 *
17044562236bSHarry Wentland 	 * Note: We do not use the maximum capable refresh rate
17054562236bSHarry Wentland 	 * of the panel, because we should never go above the field
17064562236bSHarry Wentland 	 * rate of the mode timing set.
17074562236bSHarry Wentland 	 */
17084562236bSHarry Wentland 	info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx.
17094562236bSHarry Wentland 			nominal_refresh_in_micro_hz / 1000000);
17104562236bSHarry Wentland 
17114562236bSHarry Wentland 	/* PB9 - PB27  = Reserved */
17124562236bSHarry Wentland 	for (idx = 9; idx <= 27; idx++)
17134562236bSHarry Wentland 		info_packet->sb[idx] = 0x00;
17144562236bSHarry Wentland 
17154562236bSHarry Wentland 	/* Calculate checksum */
17164562236bSHarry Wentland 	checksum += info_packet->hb0;
17174562236bSHarry Wentland 	checksum += info_packet->hb1;
17184562236bSHarry Wentland 	checksum += info_packet->hb2;
17194562236bSHarry Wentland 	checksum += info_packet->hb3;
17204562236bSHarry Wentland 
17214562236bSHarry Wentland 	for (idx = 1; idx <= payload_size; idx++)
17224562236bSHarry Wentland 		checksum += info_packet->sb[idx];
17234562236bSHarry Wentland 
17244562236bSHarry Wentland 	/* PB0 = Checksum (one byte complement) */
17254562236bSHarry Wentland 	info_packet->sb[0] = (unsigned char) (0x100 - checksum);
17264562236bSHarry Wentland 
17274562236bSHarry Wentland 	info_packet->valid = true;
17284562236bSHarry Wentland }
17294562236bSHarry Wentland 
17301646a6feSAndrew Wong static void set_hdr_static_info_packet(
17311646a6feSAndrew Wong 		struct core_surface *surface,
17321646a6feSAndrew Wong 		struct core_stream *stream,
17331646a6feSAndrew Wong 		struct hw_info_packet *info_packet)
17341646a6feSAndrew Wong {
1735e5cf325bSHarry Wentland 	uint16_t i = 0;
17361646a6feSAndrew Wong 	enum signal_type signal = stream->signal;
1737e5cf325bSHarry Wentland 	struct dc_hdr_static_metadata hdr_metadata;
1738e5cf325bSHarry Wentland 	uint32_t data;
17391646a6feSAndrew Wong 
17401646a6feSAndrew Wong 	if (!surface)
17411646a6feSAndrew Wong 		return;
17421646a6feSAndrew Wong 
1743e5cf325bSHarry Wentland 	hdr_metadata = surface->public.hdr_static_ctx;
17441646a6feSAndrew Wong 
174510bff005SYongqiang Sun 	if (!hdr_metadata.is_hdr)
174610bff005SYongqiang Sun 		return;
174710bff005SYongqiang Sun 
17481646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
17491646a6feSAndrew Wong 		info_packet->valid = true;
17501646a6feSAndrew Wong 
17511646a6feSAndrew Wong 		info_packet->hb0 = 0x87;
17521646a6feSAndrew Wong 		info_packet->hb1 = 0x01;
17531646a6feSAndrew Wong 		info_packet->hb2 = 0x1A;
17541646a6feSAndrew Wong 		i = 1;
17551646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
17561646a6feSAndrew Wong 		info_packet->valid = true;
17571646a6feSAndrew Wong 
17581646a6feSAndrew Wong 		info_packet->hb0 = 0x00;
17591646a6feSAndrew Wong 		info_packet->hb1 = 0x87;
17601646a6feSAndrew Wong 		info_packet->hb2 = 0x1D;
17611646a6feSAndrew Wong 		info_packet->hb3 = (0x13 << 2);
17621646a6feSAndrew Wong 		i = 2;
17631646a6feSAndrew Wong 	}
17641646a6feSAndrew Wong 
17651646a6feSAndrew Wong 	data = hdr_metadata.is_hdr;
17661646a6feSAndrew Wong 	info_packet->sb[i++] = data ? 0x02 : 0x00;
17671646a6feSAndrew Wong 	info_packet->sb[i++] = 0x00;
17681646a6feSAndrew Wong 
17691646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_x / 2;
17701646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17711646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17721646a6feSAndrew Wong 
17731646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_y / 2;
17741646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17751646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17761646a6feSAndrew Wong 
17771646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_x / 2;
17781646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17791646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17801646a6feSAndrew Wong 
17811646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_y / 2;
17821646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17831646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17841646a6feSAndrew Wong 
17851646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_x / 2;
17861646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17871646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17881646a6feSAndrew Wong 
17891646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_y / 2;
17901646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17911646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17921646a6feSAndrew Wong 
17931646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_x / 2;
17941646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17951646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17961646a6feSAndrew Wong 
17971646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_y / 2;
17981646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17991646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
18001646a6feSAndrew Wong 
18011646a6feSAndrew Wong 	data = hdr_metadata.max_luminance;
18021646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
18031646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
18041646a6feSAndrew Wong 
18051646a6feSAndrew Wong 	data = hdr_metadata.min_luminance;
18061646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
18071646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
18081646a6feSAndrew Wong 
18091646a6feSAndrew Wong 	data = hdr_metadata.maximum_content_light_level;
18101646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
18111646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
18121646a6feSAndrew Wong 
18131646a6feSAndrew Wong 	data = hdr_metadata.maximum_frame_average_light_level;
18141646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
18151646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
18161646a6feSAndrew Wong 
18171646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
18181646a6feSAndrew Wong 		uint32_t checksum = 0;
18191646a6feSAndrew Wong 
18201646a6feSAndrew Wong 		checksum += info_packet->hb0;
18211646a6feSAndrew Wong 		checksum += info_packet->hb1;
18221646a6feSAndrew Wong 		checksum += info_packet->hb2;
18231646a6feSAndrew Wong 
18241646a6feSAndrew Wong 		for (i = 1; i <= info_packet->hb2; i++)
18251646a6feSAndrew Wong 			checksum += info_packet->sb[i];
18261646a6feSAndrew Wong 
18271646a6feSAndrew Wong 		info_packet->sb[0] = 0x100 - checksum;
18281646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
18291646a6feSAndrew Wong 		info_packet->sb[0] = 0x01;
18301646a6feSAndrew Wong 		info_packet->sb[1] = 0x1A;
18311646a6feSAndrew Wong 	}
18321646a6feSAndrew Wong }
18331646a6feSAndrew Wong 
18344562236bSHarry Wentland static void set_vsc_info_packet(struct core_stream *stream,
18354562236bSHarry Wentland 		struct hw_info_packet *info_packet)
18364562236bSHarry Wentland {
18374562236bSHarry Wentland 	unsigned int vscPacketRevision = 0;
18384562236bSHarry Wentland 	unsigned int i;
18394562236bSHarry Wentland 
18404562236bSHarry Wentland 	if (stream->sink->link->public.psr_caps.psr_version != 0) {
18414562236bSHarry Wentland 		vscPacketRevision = 2;
18424562236bSHarry Wentland 	}
18434562236bSHarry Wentland 
18444562236bSHarry Wentland 	/* VSC packet not needed based on the features
18454562236bSHarry Wentland 	 * supported by this DP display
18464562236bSHarry Wentland 	 */
18474562236bSHarry Wentland 	if (vscPacketRevision == 0)
18484562236bSHarry Wentland 		return;
18494562236bSHarry Wentland 
18504562236bSHarry Wentland 	if (vscPacketRevision == 0x2) {
18514562236bSHarry Wentland 		/* Secondary-data Packet ID = 0*/
18524562236bSHarry Wentland 		info_packet->hb0 = 0x00;
18534562236bSHarry Wentland 		/* 07h - Packet Type Value indicating Video
18544562236bSHarry Wentland 		 * Stream Configuration packet
18554562236bSHarry Wentland 		 */
18564562236bSHarry Wentland 		info_packet->hb1 = 0x07;
18574562236bSHarry Wentland 		/* 02h = VSC SDP supporting 3D stereo and PSR
18584562236bSHarry Wentland 		 * (applies to eDP v1.3 or higher).
18594562236bSHarry Wentland 		 */
18604562236bSHarry Wentland 		info_packet->hb2 = 0x02;
18614562236bSHarry Wentland 		/* 08h = VSC packet supporting 3D stereo + PSR
18624562236bSHarry Wentland 		 * (HB2 = 02h).
18634562236bSHarry Wentland 		 */
18644562236bSHarry Wentland 		info_packet->hb3 = 0x08;
18654562236bSHarry Wentland 
18664562236bSHarry Wentland 		for (i = 0; i < 28; i++)
18674562236bSHarry Wentland 			info_packet->sb[i] = 0;
18684562236bSHarry Wentland 
18694562236bSHarry Wentland 		info_packet->valid = true;
18704562236bSHarry Wentland 	}
18714562236bSHarry Wentland 
18724562236bSHarry Wentland 	/*TODO: stereo 3D support and extend pixel encoding colorimetry*/
18734562236bSHarry Wentland }
18744562236bSHarry Wentland 
18754562236bSHarry Wentland void resource_validate_ctx_destruct(struct validate_context *context)
18764562236bSHarry Wentland {
18774562236bSHarry Wentland 	int i, j;
18784562236bSHarry Wentland 
18794562236bSHarry Wentland 	for (i = 0; i < context->target_count; i++) {
18804562236bSHarry Wentland 		for (j = 0; j < context->target_status[i].surface_count; j++)
18814562236bSHarry Wentland 			dc_surface_release(
18824562236bSHarry Wentland 				context->target_status[i].surfaces[j]);
18834562236bSHarry Wentland 
18844562236bSHarry Wentland 		context->target_status[i].surface_count = 0;
18854562236bSHarry Wentland 		dc_target_release(&context->targets[i]->public);
18864562236bSHarry Wentland 	}
18874562236bSHarry Wentland }
18884562236bSHarry Wentland 
18894562236bSHarry Wentland /*
18904562236bSHarry Wentland  * Copy src_ctx into dst_ctx and retain all surfaces and targets referenced
18914562236bSHarry Wentland  * by the src_ctx
18924562236bSHarry Wentland  */
18934562236bSHarry Wentland void resource_validate_ctx_copy_construct(
18944562236bSHarry Wentland 		const struct validate_context *src_ctx,
18954562236bSHarry Wentland 		struct validate_context *dst_ctx)
18964562236bSHarry Wentland {
18974562236bSHarry Wentland 	int i, j;
18984562236bSHarry Wentland 
18994562236bSHarry Wentland 	*dst_ctx = *src_ctx;
19004562236bSHarry Wentland 
19014562236bSHarry Wentland 	for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) {
19024562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
19034562236bSHarry Wentland 
19044562236bSHarry Wentland 		if (cur_pipe->top_pipe)
19054562236bSHarry Wentland 			cur_pipe->top_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
19064562236bSHarry Wentland 
19074562236bSHarry Wentland 		if (cur_pipe->bottom_pipe)
19084562236bSHarry Wentland 			cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
19094562236bSHarry Wentland 
19104562236bSHarry Wentland 	}
19114562236bSHarry Wentland 
19124562236bSHarry Wentland 	for (i = 0; i < dst_ctx->target_count; i++) {
19134562236bSHarry Wentland 		dc_target_retain(&dst_ctx->targets[i]->public);
19144562236bSHarry Wentland 		for (j = 0; j < dst_ctx->target_status[i].surface_count; j++)
19154562236bSHarry Wentland 			dc_surface_retain(
19164562236bSHarry Wentland 				dst_ctx->target_status[i].surfaces[j]);
19174562236bSHarry Wentland 	}
19184562236bSHarry Wentland }
19194562236bSHarry Wentland 
19204562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll(
19214562236bSHarry Wentland 		struct resource_context *res_ctx)
19224562236bSHarry Wentland {
19234562236bSHarry Wentland 	int i;
19244562236bSHarry Wentland 
19254562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; ++i) {
19264562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
19274562236bSHarry Wentland 			return res_ctx->pool->clock_sources[i];
19284562236bSHarry Wentland 	}
19294562236bSHarry Wentland 
19304562236bSHarry Wentland 	return NULL;
19314562236bSHarry Wentland }
19324562236bSHarry Wentland 
19334562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
19344562236bSHarry Wentland {
19354562236bSHarry Wentland 	enum signal_type signal = SIGNAL_TYPE_NONE;
19364562236bSHarry Wentland 	struct hw_info_frame info_frame = { { 0 } };
19374562236bSHarry Wentland 
19384562236bSHarry Wentland 	/* default all packets to invalid */
19394562236bSHarry Wentland 	info_frame.avi_info_packet.valid = false;
19404562236bSHarry Wentland 	info_frame.gamut_packet.valid = false;
19414562236bSHarry Wentland 	info_frame.vendor_info_packet.valid = false;
19424562236bSHarry Wentland 	info_frame.spd_packet.valid = false;
19434562236bSHarry Wentland 	info_frame.vsc_packet.valid = false;
19441646a6feSAndrew Wong 	info_frame.hdrsmd_packet.valid = false;
19454562236bSHarry Wentland 
19464562236bSHarry Wentland 	signal = pipe_ctx->stream->signal;
19474562236bSHarry Wentland 
19484562236bSHarry Wentland 	/* HDMi and DP have different info packets*/
19494562236bSHarry Wentland 	if (dc_is_hdmi_signal(signal)) {
19504562236bSHarry Wentland 		set_avi_info_frame(
19514562236bSHarry Wentland 			&info_frame.avi_info_packet, pipe_ctx);
19524562236bSHarry Wentland 		set_vendor_info_packet(
19534562236bSHarry Wentland 			pipe_ctx->stream, &info_frame.vendor_info_packet);
19544562236bSHarry Wentland 		set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet);
19551646a6feSAndrew Wong 		set_hdr_static_info_packet(pipe_ctx->surface,
19561646a6feSAndrew Wong 				pipe_ctx->stream, &info_frame.hdrsmd_packet);
1957a33fa99dSHarry Wentland 	} else if (dc_is_dp_signal(signal)) {
19584562236bSHarry Wentland 		set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet);
19594562236bSHarry Wentland 		set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet);
19601646a6feSAndrew Wong 		set_hdr_static_info_packet(pipe_ctx->surface,
19611646a6feSAndrew Wong 				pipe_ctx->stream, &info_frame.hdrsmd_packet);
1962a33fa99dSHarry Wentland 	}
19634562236bSHarry Wentland 
19644562236bSHarry Wentland 	translate_info_frame(&info_frame,
19654562236bSHarry Wentland 			&pipe_ctx->encoder_info_frame);
19664562236bSHarry Wentland }
19674562236bSHarry Wentland 
19684562236bSHarry Wentland enum dc_status resource_map_clock_resources(
19694562236bSHarry Wentland 		const struct core_dc *dc,
19704562236bSHarry Wentland 		struct validate_context *context)
19714562236bSHarry Wentland {
19724562236bSHarry Wentland 	int i, j, k;
19734562236bSHarry Wentland 
19744562236bSHarry Wentland 	/* acquire new resources */
19754562236bSHarry Wentland 	for (i = 0; i < context->target_count; i++) {
19764562236bSHarry Wentland 		struct core_target *target = context->targets[i];
19774562236bSHarry Wentland 
19784562236bSHarry Wentland 		for (j = 0; j < target->public.stream_count; j++) {
19794562236bSHarry Wentland 			struct core_stream *stream =
19804562236bSHarry Wentland 				DC_STREAM_TO_CORE(target->public.streams[j]);
19814562236bSHarry Wentland 
19824562236bSHarry Wentland 			if (resource_is_stream_unchanged(dc->current_context, stream))
19834562236bSHarry Wentland 				continue;
19844562236bSHarry Wentland 
19854562236bSHarry Wentland 			for (k = 0; k < MAX_PIPES; k++) {
19864562236bSHarry Wentland 				struct pipe_ctx *pipe_ctx =
19874562236bSHarry Wentland 					&context->res_ctx.pipe_ctx[k];
19884562236bSHarry Wentland 
19894562236bSHarry Wentland 				if (context->res_ctx.pipe_ctx[k].stream != stream)
19904562236bSHarry Wentland 					continue;
19914562236bSHarry Wentland 
19924562236bSHarry Wentland 				if (dc_is_dp_signal(pipe_ctx->stream->signal)
19934562236bSHarry Wentland 					|| pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
19944562236bSHarry Wentland 					pipe_ctx->clock_source =
19954562236bSHarry Wentland 						context->res_ctx.pool->dp_clock_source;
19964562236bSHarry Wentland 				else {
19974562236bSHarry Wentland 					pipe_ctx->clock_source = NULL;
19984562236bSHarry Wentland 
19994562236bSHarry Wentland 					if (!dc->public.config.disable_disp_pll_sharing)
20004562236bSHarry Wentland 						resource_find_used_clk_src_for_sharing(
20014562236bSHarry Wentland 							&context->res_ctx,
20024562236bSHarry Wentland 							pipe_ctx);
20034562236bSHarry Wentland 
20044562236bSHarry Wentland 					if (pipe_ctx->clock_source == NULL)
20054562236bSHarry Wentland 						pipe_ctx->clock_source =
20064562236bSHarry Wentland 							dc_resource_find_first_free_pll(&context->res_ctx);
20074562236bSHarry Wentland 				}
20084562236bSHarry Wentland 
20094562236bSHarry Wentland 				if (pipe_ctx->clock_source == NULL)
20104562236bSHarry Wentland 					return DC_NO_CLOCK_SOURCE_RESOURCE;
20114562236bSHarry Wentland 
20124562236bSHarry Wentland 				resource_reference_clock_source(
20134562236bSHarry Wentland 						&context->res_ctx,
20144562236bSHarry Wentland 						pipe_ctx->clock_source);
20154562236bSHarry Wentland 
20164562236bSHarry Wentland 				/* only one cs per stream regardless of mpo */
20174562236bSHarry Wentland 				break;
20184562236bSHarry Wentland 			}
20194562236bSHarry Wentland 		}
20204562236bSHarry Wentland 	}
20214562236bSHarry Wentland 
20224562236bSHarry Wentland 	return DC_OK;
20234562236bSHarry Wentland }
20244562236bSHarry Wentland 
20254562236bSHarry Wentland /*
20264562236bSHarry Wentland  * Note: We need to disable output if clock sources change,
20274562236bSHarry Wentland  * since bios does optimization and doesn't apply if changing
20284562236bSHarry Wentland  * PHY when not already disabled.
20294562236bSHarry Wentland  */
20304562236bSHarry Wentland bool pipe_need_reprogram(
20314562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx_old,
20324562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
20334562236bSHarry Wentland {
20344562236bSHarry Wentland 	if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
20354562236bSHarry Wentland 		return true;
20364562236bSHarry Wentland 
20374562236bSHarry Wentland 	if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
20384562236bSHarry Wentland 		return true;
20394562236bSHarry Wentland 
20404562236bSHarry Wentland 	if (pipe_ctx_old->audio != pipe_ctx->audio)
20414562236bSHarry Wentland 		return true;
20424562236bSHarry Wentland 
20434562236bSHarry Wentland 	if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
20444562236bSHarry Wentland 			&& pipe_ctx_old->stream != pipe_ctx->stream)
20454562236bSHarry Wentland 		return true;
20464562236bSHarry Wentland 
20474562236bSHarry Wentland 	if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc)
20484562236bSHarry Wentland 		return true;
20494562236bSHarry Wentland 
20504562236bSHarry Wentland 	if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
20514562236bSHarry Wentland 		return true;
20524562236bSHarry Wentland 
20534562236bSHarry Wentland 
20544562236bSHarry Wentland 	return false;
20554562236bSHarry Wentland }
2056