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");
13817a96033SJulia Lawall 	}
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;
3448693049aSTony Cheng 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
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 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
3624562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_420BPP12;
3634562236bSHarry Wentland 		break;
364ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
365ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
366ffbcd19aSVitaly Prosyak 		dal_pixel_format = PIXEL_FORMAT_420BPP15;
367ffbcd19aSVitaly Prosyak 		break;
3684562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
3694562236bSHarry Wentland 	default:
3704562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
3714562236bSHarry Wentland 		break;
3724562236bSHarry Wentland 	}
3734562236bSHarry Wentland 	return dal_pixel_format;
3744562236bSHarry Wentland }
3754562236bSHarry Wentland 
3764562236bSHarry Wentland static void rect_swap_helper(struct rect *rect)
3774562236bSHarry Wentland {
3784562236bSHarry Wentland 	uint32_t temp = 0;
3794562236bSHarry Wentland 
3804562236bSHarry Wentland 	temp = rect->height;
3814562236bSHarry Wentland 	rect->height = rect->width;
3824562236bSHarry Wentland 	rect->width = temp;
3834562236bSHarry Wentland 
3844562236bSHarry Wentland 	temp = rect->x;
3854562236bSHarry Wentland 	rect->x = rect->y;
3864562236bSHarry Wentland 	rect->y = temp;
3874562236bSHarry Wentland }
3884562236bSHarry Wentland 
3894562236bSHarry Wentland static void calculate_viewport(
3904562236bSHarry Wentland 		const struct dc_surface *surface,
3914562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
3924562236bSHarry Wentland {
3934562236bSHarry Wentland 	struct rect stream_src = pipe_ctx->stream->public.src;
3944562236bSHarry Wentland 	struct rect src = surface->src_rect;
3954562236bSHarry Wentland 	struct rect dst = surface->dst_rect;
3964562236bSHarry Wentland 	struct rect surface_clip = surface->clip_rect;
3974562236bSHarry Wentland 	struct rect clip = {0};
3984562236bSHarry Wentland 
3994562236bSHarry Wentland 
4004562236bSHarry Wentland 	if (surface->rotation == ROTATION_ANGLE_90 ||
4014562236bSHarry Wentland 	    surface->rotation == ROTATION_ANGLE_270) {
4024562236bSHarry Wentland 		rect_swap_helper(&src);
4034562236bSHarry Wentland 		rect_swap_helper(&dst);
4044562236bSHarry Wentland 		rect_swap_helper(&surface_clip);
4054562236bSHarry Wentland 		rect_swap_helper(&stream_src);
4064562236bSHarry Wentland 	}
4074562236bSHarry Wentland 
4084562236bSHarry Wentland 	/* The actual clip is an intersection between stream
4094562236bSHarry Wentland 	 * source and surface clip
4104562236bSHarry Wentland 	 */
4114562236bSHarry Wentland 	clip.x = stream_src.x > surface_clip.x ?
4124562236bSHarry Wentland 			stream_src.x : surface_clip.x;
4134562236bSHarry Wentland 
4144562236bSHarry Wentland 	clip.width = stream_src.x + stream_src.width <
4154562236bSHarry Wentland 			surface_clip.x + surface_clip.width ?
4164562236bSHarry Wentland 			stream_src.x + stream_src.width - clip.x :
4174562236bSHarry Wentland 			surface_clip.x + surface_clip.width - clip.x ;
4184562236bSHarry Wentland 
4194562236bSHarry Wentland 	clip.y = stream_src.y > surface_clip.y ?
4204562236bSHarry Wentland 			stream_src.y : surface_clip.y;
4214562236bSHarry Wentland 
4224562236bSHarry Wentland 	clip.height = stream_src.y + stream_src.height <
4234562236bSHarry Wentland 			surface_clip.y + surface_clip.height ?
4244562236bSHarry Wentland 			stream_src.y + stream_src.height - clip.y :
4254562236bSHarry Wentland 			surface_clip.y + surface_clip.height - clip.y ;
4264562236bSHarry Wentland 
4274562236bSHarry Wentland 	/* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
4284562236bSHarry Wentland 	 * num_pixels = clip.num_pix * scl_ratio
4294562236bSHarry Wentland 	 */
4304562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) *
4314562236bSHarry Wentland 			src.width / dst.width;
4324562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.width = clip.width *
4334562236bSHarry Wentland 			src.width / dst.width;
4344562236bSHarry Wentland 
4354562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) *
4364562236bSHarry Wentland 			src.height / dst.height;
4374562236bSHarry Wentland 	pipe_ctx->scl_data.viewport.height = clip.height *
4384562236bSHarry Wentland 			src.height / dst.height;
4394562236bSHarry Wentland 
4404562236bSHarry Wentland 	/* Minimum viewport such that 420/422 chroma vp is non 0 */
4414562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.width < 2)
4424562236bSHarry Wentland 		pipe_ctx->scl_data.viewport.width = 2;
4434562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.height < 2)
4444562236bSHarry Wentland 		pipe_ctx->scl_data.viewport.height = 2;
4454562236bSHarry Wentland }
4464562236bSHarry Wentland 
4474562236bSHarry Wentland static void calculate_recout(
4484562236bSHarry Wentland 		const struct dc_surface *surface,
4494562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
4504562236bSHarry Wentland {
4514562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
4524562236bSHarry Wentland 	struct rect clip = surface->clip_rect;
4534562236bSHarry Wentland 
4544562236bSHarry Wentland 	pipe_ctx->scl_data.recout.x = stream->public.dst.x;
4554562236bSHarry Wentland 	if (stream->public.src.x < clip.x)
4564562236bSHarry Wentland 		pipe_ctx->scl_data.recout.x += (clip.x
4574562236bSHarry Wentland 			- stream->public.src.x) * stream->public.dst.width
4584562236bSHarry Wentland 						/ stream->public.src.width;
4594562236bSHarry Wentland 
4604562236bSHarry Wentland 	pipe_ctx->scl_data.recout.width = clip.width *
4614562236bSHarry Wentland 			stream->public.dst.width / stream->public.src.width;
4624562236bSHarry Wentland 	if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x >
4634562236bSHarry Wentland 			stream->public.dst.x + stream->public.dst.width)
4644562236bSHarry Wentland 		pipe_ctx->scl_data.recout.width =
4654562236bSHarry Wentland 			stream->public.dst.x + stream->public.dst.width
4664562236bSHarry Wentland 						- pipe_ctx->scl_data.recout.x;
4674562236bSHarry Wentland 
4684562236bSHarry Wentland 	pipe_ctx->scl_data.recout.y = stream->public.dst.y;
4694562236bSHarry Wentland 	if (stream->public.src.y < clip.y)
4704562236bSHarry Wentland 		pipe_ctx->scl_data.recout.y += (clip.y
4714562236bSHarry Wentland 			- stream->public.src.y) * stream->public.dst.height
4724562236bSHarry Wentland 						/ stream->public.src.height;
4734562236bSHarry Wentland 
4744562236bSHarry Wentland 	pipe_ctx->scl_data.recout.height = clip.height *
4754562236bSHarry Wentland 			stream->public.dst.height / stream->public.src.height;
4764562236bSHarry Wentland 	if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y >
4774562236bSHarry Wentland 			stream->public.dst.y + stream->public.dst.height)
4784562236bSHarry Wentland 		pipe_ctx->scl_data.recout.height =
4794562236bSHarry Wentland 			stream->public.dst.y + stream->public.dst.height
4804562236bSHarry Wentland 						- pipe_ctx->scl_data.recout.y;
4814562236bSHarry Wentland }
4824562236bSHarry Wentland 
4834562236bSHarry Wentland static void calculate_scaling_ratios(
4844562236bSHarry Wentland 		const struct dc_surface *surface,
4854562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
4864562236bSHarry Wentland {
4874562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
4884562236bSHarry Wentland 	const uint32_t in_w = stream->public.src.width;
4894562236bSHarry Wentland 	const uint32_t in_h = stream->public.src.height;
4904562236bSHarry Wentland 	const uint32_t out_w = stream->public.dst.width;
4914562236bSHarry Wentland 	const uint32_t out_h = stream->public.dst.height;
4924562236bSHarry Wentland 
4934562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction(
4944562236bSHarry Wentland 					surface->src_rect.width,
4954562236bSHarry Wentland 					surface->dst_rect.width);
4964562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction(
4974562236bSHarry Wentland 					surface->src_rect.height,
4984562236bSHarry Wentland 					surface->dst_rect.height);
4994562236bSHarry Wentland 
5004562236bSHarry Wentland 	if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
5014562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz.value *= 2;
5024562236bSHarry Wentland 	else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
5034562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert.value *= 2;
5044562236bSHarry Wentland 
5054562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert.value = div64_s64(
5064562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert.value * in_h, out_h);
5074562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz.value = div64_s64(
5084562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz.value * in_w, out_w);
5094562236bSHarry Wentland 
5104562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz;
5114562236bSHarry Wentland 	pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert;
5124562236bSHarry Wentland 
5134562236bSHarry Wentland 	if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) {
5144562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.horz_c.value /= 2;
5154562236bSHarry Wentland 		pipe_ctx->scl_data.ratios.vert_c.value /= 2;
5164562236bSHarry Wentland 	}
5174562236bSHarry Wentland }
5184562236bSHarry Wentland 
5194562236bSHarry Wentland bool resource_build_scaling_params(
5204562236bSHarry Wentland 	const struct dc_surface *surface,
5214562236bSHarry Wentland 	struct pipe_ctx *pipe_ctx)
5224562236bSHarry Wentland {
5234562236bSHarry Wentland 	bool res;
5244562236bSHarry Wentland 	struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
5254562236bSHarry Wentland 	/* Important: scaling ratio calculation requires pixel format,
5264562236bSHarry Wentland 	 * lb depth calculation requires recout and taps require scaling ratios.
5274562236bSHarry Wentland 	 */
5284562236bSHarry Wentland 	pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format);
5294562236bSHarry Wentland 
5304562236bSHarry Wentland 	calculate_viewport(surface, pipe_ctx);
5314562236bSHarry Wentland 
5324562236bSHarry Wentland 	if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16)
5334562236bSHarry Wentland 		return false;
5344562236bSHarry Wentland 
5354562236bSHarry Wentland 	calculate_scaling_ratios(surface, pipe_ctx);
5364562236bSHarry Wentland 
5374562236bSHarry Wentland 	calculate_recout(surface, pipe_ctx);
5384562236bSHarry Wentland 
5394562236bSHarry Wentland 	/**
5404562236bSHarry Wentland 	 * Setting line buffer pixel depth to 24bpp yields banding
5414562236bSHarry Wentland 	 * on certain displays, such as the Sharp 4k
5424562236bSHarry Wentland 	 */
5434562236bSHarry Wentland 	pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
5444562236bSHarry Wentland 
5454562236bSHarry Wentland 	pipe_ctx->scl_data.h_active = timing->h_addressable;
5464562236bSHarry Wentland 	pipe_ctx->scl_data.v_active = timing->v_addressable;
5474562236bSHarry Wentland 
5484562236bSHarry Wentland 	/* Taps calculations */
5494562236bSHarry Wentland 	res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
5504562236bSHarry Wentland 		pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
5514562236bSHarry Wentland 
5524562236bSHarry Wentland 	if (!res) {
5534562236bSHarry Wentland 		/* Try 24 bpp linebuffer */
5544562236bSHarry Wentland 		pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
5554562236bSHarry Wentland 
5564562236bSHarry Wentland 		res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
5574562236bSHarry Wentland 			pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
5584562236bSHarry Wentland 	}
5594562236bSHarry Wentland 
5604562236bSHarry Wentland 	dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
5614562236bSHarry Wentland 				"%s: Viewport:\nheight:%d width:%d x:%d "
5624562236bSHarry Wentland 				"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
5634562236bSHarry Wentland 				"y:%d\n",
5644562236bSHarry Wentland 				__func__,
5654562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.height,
5664562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.width,
5674562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.x,
5684562236bSHarry Wentland 				pipe_ctx->scl_data.viewport.y,
5694562236bSHarry Wentland 				surface->dst_rect.height,
5704562236bSHarry Wentland 				surface->dst_rect.width,
5714562236bSHarry Wentland 				surface->dst_rect.x,
5724562236bSHarry Wentland 				surface->dst_rect.y);
5734562236bSHarry Wentland 
5744562236bSHarry Wentland 	return res;
5754562236bSHarry Wentland }
5764562236bSHarry Wentland 
5774562236bSHarry Wentland 
5784562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context(
5794562236bSHarry Wentland 	const struct core_dc *dc,
5804562236bSHarry Wentland 	struct validate_context *context)
5814562236bSHarry Wentland {
5824562236bSHarry Wentland 	int i;
5834562236bSHarry Wentland 
5844562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
5854562236bSHarry Wentland 		if (context->res_ctx.pipe_ctx[i].surface != NULL &&
5864562236bSHarry Wentland 				context->res_ctx.pipe_ctx[i].stream != NULL)
5874562236bSHarry Wentland 			if (!resource_build_scaling_params(
5884562236bSHarry Wentland 				&context->res_ctx.pipe_ctx[i].surface->public,
5894562236bSHarry Wentland 				&context->res_ctx.pipe_ctx[i]))
590f84a8161STony Cheng 				return DC_FAIL_SCALING;
5914562236bSHarry Wentland 	}
5924562236bSHarry Wentland 
5934562236bSHarry Wentland 	return DC_OK;
5944562236bSHarry Wentland }
5954562236bSHarry Wentland 
596ab2541b6SAric Cyr static void detach_surfaces_for_stream(
5974562236bSHarry Wentland 		struct validate_context *context,
598ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
5994562236bSHarry Wentland {
6004562236bSHarry Wentland 	int i;
601ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
6024562236bSHarry Wentland 
6034562236bSHarry Wentland 	for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
6044562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i];
6054562236bSHarry Wentland 		if (cur_pipe->stream == stream) {
6064562236bSHarry Wentland 			cur_pipe->surface = NULL;
6074562236bSHarry Wentland 			cur_pipe->top_pipe = NULL;
6084562236bSHarry Wentland 			cur_pipe->bottom_pipe = NULL;
6094562236bSHarry Wentland 		}
6104562236bSHarry Wentland 	}
6114562236bSHarry Wentland }
6124562236bSHarry Wentland 
6134562236bSHarry Wentland struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx)
6144562236bSHarry Wentland {
6154562236bSHarry Wentland 	int i;
6164562236bSHarry Wentland 	struct pipe_ctx *secondary_pipe = NULL;
6174562236bSHarry Wentland 
6184562236bSHarry Wentland 	/*
6194562236bSHarry Wentland 	 * search backwards for the second pipe to keep pipe
6204562236bSHarry Wentland 	 * assignment more consistent
6214562236bSHarry Wentland 	 */
6224562236bSHarry Wentland 
6234562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
6244562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == NULL) {
6254562236bSHarry Wentland 			secondary_pipe = &res_ctx->pipe_ctx[i];
6264562236bSHarry Wentland 			secondary_pipe->pipe_idx = i;
6274562236bSHarry Wentland 			break;
6284562236bSHarry Wentland 		}
6294562236bSHarry Wentland 	}
6304562236bSHarry Wentland 
6314562236bSHarry Wentland 
6324562236bSHarry Wentland 	return secondary_pipe;
6334562236bSHarry Wentland }
6344562236bSHarry Wentland 
6354562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream(
6364562236bSHarry Wentland 		struct resource_context *res_ctx,
6374562236bSHarry Wentland 		const struct core_stream *stream)
6384562236bSHarry Wentland {
6394562236bSHarry Wentland 	int i;
6404562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->pipe_count; i++) {
6414562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
6424562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].top_pipe) {
6434562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
6444562236bSHarry Wentland 			break;
6454562236bSHarry Wentland 		}
6464562236bSHarry Wentland 	}
6474562236bSHarry Wentland 	return NULL;
6484562236bSHarry Wentland }
6494562236bSHarry Wentland 
6504562236bSHarry Wentland /*
651ab2541b6SAric Cyr  * A free_pipe for a stream is defined here as a pipe
652ab2541b6SAric Cyr  * that has no surface attached yet
6534562236bSHarry Wentland  */
654ab2541b6SAric Cyr static struct pipe_ctx *acquire_free_pipe_for_stream(
6554562236bSHarry Wentland 		struct resource_context *res_ctx,
656ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
6574562236bSHarry Wentland {
6584562236bSHarry Wentland 	int i;
659ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
6604562236bSHarry Wentland 
6614562236bSHarry Wentland 	struct pipe_ctx *head_pipe = NULL;
6624562236bSHarry Wentland 
6634562236bSHarry Wentland 	/* Find head pipe, which has the back end set up*/
6644562236bSHarry Wentland 
6654562236bSHarry Wentland 	head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
6664562236bSHarry Wentland 
6674562236bSHarry Wentland 	if (!head_pipe)
6684562236bSHarry Wentland 		ASSERT(0);
6694562236bSHarry Wentland 
6704562236bSHarry Wentland 	if (!head_pipe->surface)
6714562236bSHarry Wentland 		return head_pipe;
6724562236bSHarry Wentland 
6734562236bSHarry Wentland 	/* Re-use pipe already acquired for this stream if available*/
6744562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
6754562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
6764562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].surface) {
6774562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
6784562236bSHarry Wentland 		}
6794562236bSHarry Wentland 	}
6804562236bSHarry Wentland 
6814562236bSHarry Wentland 	/*
6824562236bSHarry Wentland 	 * At this point we have no re-useable pipe for this stream and we need
6834562236bSHarry Wentland 	 * to acquire an idle one to satisfy the request
6844562236bSHarry Wentland 	 */
6854562236bSHarry Wentland 
6864562236bSHarry Wentland 	if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer)
6874562236bSHarry Wentland 		return NULL;
6884562236bSHarry Wentland 
6894562236bSHarry Wentland 	return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream);
6904562236bSHarry Wentland 
6914562236bSHarry Wentland }
6924562236bSHarry Wentland 
693ab2541b6SAric Cyr static void release_free_pipes_for_stream(
6944562236bSHarry Wentland 		struct resource_context *res_ctx,
695ab2541b6SAric Cyr 		const struct dc_stream *dc_stream)
6964562236bSHarry Wentland {
6974562236bSHarry Wentland 	int i;
698ab2541b6SAric Cyr 	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
6994562236bSHarry Wentland 
7004562236bSHarry Wentland 	for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
7014562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
7024562236bSHarry Wentland 				!res_ctx->pipe_ctx[i].surface) {
7034562236bSHarry Wentland 			res_ctx->pipe_ctx[i].stream = NULL;
7044562236bSHarry Wentland 		}
7054562236bSHarry Wentland 	}
7064562236bSHarry Wentland }
7074562236bSHarry Wentland 
7084562236bSHarry Wentland bool resource_attach_surfaces_to_context(
7094562236bSHarry Wentland 		const struct dc_surface * const *surfaces,
7104562236bSHarry Wentland 		int surface_count,
711ab2541b6SAric Cyr 		const struct dc_stream *dc_stream,
7124562236bSHarry Wentland 		struct validate_context *context)
7134562236bSHarry Wentland {
7144562236bSHarry Wentland 	int i;
7154562236bSHarry Wentland 	struct pipe_ctx *tail_pipe;
716ab2541b6SAric Cyr 	struct dc_stream_status *stream_status = NULL;
7174562236bSHarry Wentland 
7184562236bSHarry Wentland 
7194562236bSHarry Wentland 	if (surface_count > MAX_SURFACE_NUM) {
7204562236bSHarry Wentland 		dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
7214562236bSHarry Wentland 			surface_count, MAX_SURFACE_NUM);
7224562236bSHarry Wentland 		return false;
7234562236bSHarry Wentland 	}
7244562236bSHarry Wentland 
725ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++)
726ab2541b6SAric Cyr 		if (&context->streams[i]->public == dc_stream) {
727ab2541b6SAric Cyr 			stream_status = &context->stream_status[i];
7284562236bSHarry Wentland 			break;
7294562236bSHarry Wentland 		}
730ab2541b6SAric Cyr 	if (stream_status == NULL) {
731ab2541b6SAric Cyr 		dm_error("Existing stream not found; failed to attach surfaces\n");
7324562236bSHarry Wentland 		return false;
7334562236bSHarry Wentland 	}
7344562236bSHarry Wentland 
7354562236bSHarry Wentland 	/* retain new surfaces */
7364562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
7374562236bSHarry Wentland 		dc_surface_retain(surfaces[i]);
7384562236bSHarry Wentland 
739ab2541b6SAric Cyr 	detach_surfaces_for_stream(context, dc_stream);
7404562236bSHarry Wentland 
7414562236bSHarry Wentland 	/* release existing surfaces*/
742ab2541b6SAric Cyr 	for (i = 0; i < stream_status->surface_count; i++)
743ab2541b6SAric Cyr 		dc_surface_release(stream_status->surfaces[i]);
7444562236bSHarry Wentland 
745ab2541b6SAric Cyr 	for (i = surface_count; i < stream_status->surface_count; i++)
746ab2541b6SAric Cyr 		stream_status->surfaces[i] = NULL;
7474562236bSHarry Wentland 
748ab2541b6SAric Cyr 	stream_status->surface_count = 0;
7494562236bSHarry Wentland 
7504562236bSHarry Wentland 	if (surface_count == 0)
7514562236bSHarry Wentland 		return true;
7524562236bSHarry Wentland 
7534562236bSHarry Wentland 	tail_pipe = NULL;
7544562236bSHarry Wentland 	for (i = 0; i < surface_count; i++) {
7554562236bSHarry Wentland 		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
756ab2541b6SAric Cyr 		struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(
757ab2541b6SAric Cyr 				&context->res_ctx, dc_stream);
7584562236bSHarry Wentland 
7594562236bSHarry Wentland 		if (!free_pipe) {
760ab2541b6SAric Cyr 			stream_status->surfaces[i] = NULL;
7614562236bSHarry Wentland 			return false;
7624562236bSHarry Wentland 		}
7634562236bSHarry Wentland 
7644562236bSHarry Wentland 		free_pipe->surface = surface;
7654562236bSHarry Wentland 
7664562236bSHarry Wentland 		if (tail_pipe) {
7674562236bSHarry Wentland 			free_pipe->top_pipe = tail_pipe;
7684562236bSHarry Wentland 			tail_pipe->bottom_pipe = free_pipe;
7694562236bSHarry Wentland 		}
7704562236bSHarry Wentland 
7714562236bSHarry Wentland 		tail_pipe = free_pipe;
7724562236bSHarry Wentland 	}
7734562236bSHarry Wentland 
774ab2541b6SAric Cyr 	release_free_pipes_for_stream(&context->res_ctx, dc_stream);
7754562236bSHarry Wentland 
7764562236bSHarry Wentland 	/* assign new surfaces*/
7774562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
778ab2541b6SAric Cyr 		stream_status->surfaces[i] = surfaces[i];
7794562236bSHarry Wentland 
780ab2541b6SAric Cyr 	stream_status->surface_count = surface_count;
7814562236bSHarry Wentland 
7824562236bSHarry Wentland 	return true;
7834562236bSHarry Wentland }
7844562236bSHarry Wentland 
7854562236bSHarry Wentland 
7864562236bSHarry Wentland static bool is_timing_changed(const struct core_stream *cur_stream,
7874562236bSHarry Wentland 		const struct core_stream *new_stream)
7884562236bSHarry Wentland {
7894562236bSHarry Wentland 	if (cur_stream == NULL)
7904562236bSHarry Wentland 		return true;
7914562236bSHarry Wentland 
7924562236bSHarry Wentland 	/* If sink pointer changed, it means this is a hotplug, we should do
7934562236bSHarry Wentland 	 * full hw setting.
7944562236bSHarry Wentland 	 */
7954562236bSHarry Wentland 	if (cur_stream->sink != new_stream->sink)
7964562236bSHarry Wentland 		return true;
7974562236bSHarry Wentland 
7984562236bSHarry Wentland 	/* If output color space is changed, need to reprogram info frames */
7994562236bSHarry Wentland 	if (cur_stream->public.output_color_space !=
8004562236bSHarry Wentland 			new_stream->public.output_color_space)
8014562236bSHarry Wentland 		return true;
8024562236bSHarry Wentland 
8034562236bSHarry Wentland 	return memcmp(
8044562236bSHarry Wentland 		&cur_stream->public.timing,
8054562236bSHarry Wentland 		&new_stream->public.timing,
8064562236bSHarry Wentland 		sizeof(struct dc_crtc_timing)) != 0;
8074562236bSHarry Wentland }
8084562236bSHarry Wentland 
8094562236bSHarry Wentland static bool are_stream_backends_same(
8104562236bSHarry Wentland 	const struct core_stream *stream_a, const struct core_stream *stream_b)
8114562236bSHarry Wentland {
8124562236bSHarry Wentland 	if (stream_a == stream_b)
8134562236bSHarry Wentland 		return true;
8144562236bSHarry Wentland 
8154562236bSHarry Wentland 	if (stream_a == NULL || stream_b == NULL)
8164562236bSHarry Wentland 		return false;
8174562236bSHarry Wentland 
8184562236bSHarry Wentland 	if (is_timing_changed(stream_a, stream_b))
8194562236bSHarry Wentland 		return false;
8204562236bSHarry Wentland 
8214562236bSHarry Wentland 	return true;
8224562236bSHarry Wentland }
8234562236bSHarry Wentland 
824ab2541b6SAric Cyr bool is_stream_unchanged(
825ab2541b6SAric Cyr 	const struct core_stream *old_stream, const struct core_stream *stream)
8264562236bSHarry Wentland {
827ab2541b6SAric Cyr 	if (old_stream == stream)
8284562236bSHarry Wentland 		return true;
8294562236bSHarry Wentland 
8304562236bSHarry Wentland 	if (!are_stream_backends_same(old_stream, stream))
8314562236bSHarry Wentland 		return false;
8324562236bSHarry Wentland 
8334562236bSHarry Wentland 	return true;
8344562236bSHarry Wentland }
8354562236bSHarry Wentland 
8364562236bSHarry Wentland bool resource_validate_attach_surfaces(
8374562236bSHarry Wentland 		const struct dc_validation_set set[],
8384562236bSHarry Wentland 		int set_count,
8394562236bSHarry Wentland 		const struct validate_context *old_context,
8404562236bSHarry Wentland 		struct validate_context *context)
8414562236bSHarry Wentland {
8424562236bSHarry Wentland 	int i, j;
8434562236bSHarry Wentland 
8444562236bSHarry Wentland 	for (i = 0; i < set_count; i++) {
845ab2541b6SAric Cyr 		for (j = 0; j < old_context->stream_count; j++)
846ab2541b6SAric Cyr 			if (is_stream_unchanged(
847ab2541b6SAric Cyr 					old_context->streams[j],
848ab2541b6SAric Cyr 					context->streams[i])) {
8494562236bSHarry Wentland 				if (!resource_attach_surfaces_to_context(
850ab2541b6SAric Cyr 						old_context->stream_status[j].surfaces,
851ab2541b6SAric Cyr 						old_context->stream_status[j].surface_count,
852ab2541b6SAric Cyr 						&context->streams[i]->public,
8534562236bSHarry Wentland 						context))
8544562236bSHarry Wentland 					return false;
855ab2541b6SAric Cyr 				context->stream_status[i] = old_context->stream_status[j];
8564562236bSHarry Wentland 			}
8574562236bSHarry Wentland 		if (set[i].surface_count != 0)
8584562236bSHarry Wentland 			if (!resource_attach_surfaces_to_context(
8594562236bSHarry Wentland 					set[i].surfaces,
8604562236bSHarry Wentland 					set[i].surface_count,
861ab2541b6SAric Cyr 					&context->streams[i]->public,
8624562236bSHarry Wentland 					context))
8634562236bSHarry Wentland 				return false;
8644562236bSHarry Wentland 
8654562236bSHarry Wentland 	}
8664562236bSHarry Wentland 
8674562236bSHarry Wentland 	return true;
8684562236bSHarry Wentland }
8694562236bSHarry Wentland 
8704562236bSHarry Wentland /* Maximum TMDS single link pixel clock 165MHz */
8714562236bSHarry Wentland #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
8724562236bSHarry Wentland 
8734562236bSHarry Wentland static void set_stream_engine_in_use(
8744562236bSHarry Wentland 		struct resource_context *res_ctx,
8754562236bSHarry Wentland 		struct stream_encoder *stream_enc)
8764562236bSHarry Wentland {
8774562236bSHarry Wentland 	int i;
8784562236bSHarry Wentland 
8794562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
8804562236bSHarry Wentland 		if (res_ctx->pool->stream_enc[i] == stream_enc)
8814562236bSHarry Wentland 			res_ctx->is_stream_enc_acquired[i] = true;
8824562236bSHarry Wentland 	}
8834562236bSHarry Wentland }
8844562236bSHarry Wentland 
8854562236bSHarry Wentland /* TODO: release audio object */
8864562236bSHarry Wentland static void set_audio_in_use(
8874562236bSHarry Wentland 		struct resource_context *res_ctx,
8884562236bSHarry Wentland 		struct audio *audio)
8894562236bSHarry Wentland {
8904562236bSHarry Wentland 	int i;
8914562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->audio_count; i++) {
8924562236bSHarry Wentland 		if (res_ctx->pool->audios[i] == audio) {
8934562236bSHarry Wentland 			res_ctx->is_audio_acquired[i] = true;
8944562236bSHarry Wentland 		}
8954562236bSHarry Wentland 	}
8964562236bSHarry Wentland }
8974562236bSHarry Wentland 
8984562236bSHarry Wentland static int acquire_first_free_pipe(
8994562236bSHarry Wentland 		struct resource_context *res_ctx,
9004562236bSHarry Wentland 		struct core_stream *stream)
9014562236bSHarry Wentland {
9024562236bSHarry Wentland 	int i;
9034562236bSHarry Wentland 
9044562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->pipe_count; i++) {
9054562236bSHarry Wentland 		if (!res_ctx->pipe_ctx[i].stream) {
9064562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
9074562236bSHarry Wentland 
9084562236bSHarry Wentland 			pipe_ctx->tg = res_ctx->pool->timing_generators[i];
9094562236bSHarry Wentland 			pipe_ctx->mi = res_ctx->pool->mis[i];
9104562236bSHarry Wentland 			pipe_ctx->ipp = res_ctx->pool->ipps[i];
9114562236bSHarry Wentland 			pipe_ctx->xfm = res_ctx->pool->transforms[i];
9124562236bSHarry Wentland 			pipe_ctx->opp = res_ctx->pool->opps[i];
9134562236bSHarry Wentland 			pipe_ctx->dis_clk = res_ctx->pool->display_clock;
9144562236bSHarry Wentland 			pipe_ctx->pipe_idx = i;
9154562236bSHarry Wentland 
9164562236bSHarry Wentland 			pipe_ctx->stream = stream;
9174562236bSHarry Wentland 			return i;
9184562236bSHarry Wentland 		}
9194562236bSHarry Wentland 	}
9204562236bSHarry Wentland 	return -1;
9214562236bSHarry Wentland }
9224562236bSHarry Wentland 
9234562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link(
9244562236bSHarry Wentland 		struct resource_context *res_ctx,
9254562236bSHarry Wentland 		struct core_stream *stream)
9264562236bSHarry Wentland {
9274562236bSHarry Wentland 	int i;
9284562236bSHarry Wentland 	int j = -1;
9294562236bSHarry Wentland 	struct core_link *link = stream->sink->link;
9304562236bSHarry Wentland 
9314562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
9324562236bSHarry Wentland 		if (!res_ctx->is_stream_enc_acquired[i] &&
9334562236bSHarry Wentland 					res_ctx->pool->stream_enc[i]) {
9344562236bSHarry Wentland 			/* Store first available for MST second display
9354562236bSHarry Wentland 			 * in daisy chain use case */
9364562236bSHarry Wentland 			j = i;
9374562236bSHarry Wentland 			if (res_ctx->pool->stream_enc[i]->id ==
9384562236bSHarry Wentland 					link->link_enc->preferred_engine)
9394562236bSHarry Wentland 				return res_ctx->pool->stream_enc[i];
9404562236bSHarry Wentland 		}
9414562236bSHarry Wentland 	}
9424562236bSHarry Wentland 
9434562236bSHarry Wentland 	/*
9444562236bSHarry Wentland 	 * below can happen in cases when stream encoder is acquired:
9454562236bSHarry Wentland 	 * 1) for second MST display in chain, so preferred engine already
9464562236bSHarry Wentland 	 * acquired;
9474562236bSHarry Wentland 	 * 2) for another link, which preferred engine already acquired by any
9484562236bSHarry Wentland 	 * MST configuration.
9494562236bSHarry Wentland 	 *
9504562236bSHarry Wentland 	 * If signal is of DP type and preferred engine not found, return last available
9514562236bSHarry Wentland 	 *
9524562236bSHarry Wentland 	 * TODO - This is just a patch up and a generic solution is
9534562236bSHarry Wentland 	 * required for non DP connectors.
9544562236bSHarry Wentland 	 */
9554562236bSHarry Wentland 
9564562236bSHarry Wentland 	if (j >= 0 && dc_is_dp_signal(stream->signal))
9574562236bSHarry Wentland 		return res_ctx->pool->stream_enc[j];
9584562236bSHarry Wentland 
9594562236bSHarry Wentland 	return NULL;
9604562236bSHarry Wentland }
9614562236bSHarry Wentland 
9624562236bSHarry Wentland static struct audio *find_first_free_audio(struct resource_context *res_ctx)
9634562236bSHarry Wentland {
9644562236bSHarry Wentland 	int i;
9654562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->audio_count; i++) {
9664562236bSHarry Wentland 		if (res_ctx->is_audio_acquired[i] == false) {
9674562236bSHarry Wentland 			return res_ctx->pool->audios[i];
9684562236bSHarry Wentland 		}
9694562236bSHarry Wentland 	}
9704562236bSHarry Wentland 
9714562236bSHarry Wentland 	return 0;
9724562236bSHarry Wentland }
9734562236bSHarry Wentland 
9744562236bSHarry Wentland static void update_stream_signal(struct core_stream *stream)
9754562236bSHarry Wentland {
9764562236bSHarry Wentland 	const struct dc_sink *dc_sink = stream->public.sink;
9774562236bSHarry Wentland 
9782796eaeeSJoshua Aberback 	if (dc_sink->sink_signal == SIGNAL_TYPE_NONE)
9792796eaeeSJoshua Aberback 		stream->signal = stream->sink->link->public.connector_signal;
9802796eaeeSJoshua Aberback 	else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
9812796eaeeSJoshua Aberback 			dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK)
9824562236bSHarry Wentland 		/* For asic supports dual link DVI, we should adjust signal type
9834562236bSHarry Wentland 		 * based on timing pixel clock. If pixel clock more than 165Mhz,
9844562236bSHarry Wentland 		 * signal is dual link, otherwise, single link.
9854562236bSHarry Wentland 		 */
9862796eaeeSJoshua Aberback 		if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
9874562236bSHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
9884562236bSHarry Wentland 		else
9894562236bSHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
9902796eaeeSJoshua Aberback 	else
9912796eaeeSJoshua Aberback 		stream->signal = dc_sink->sink_signal;
9924562236bSHarry Wentland }
9934562236bSHarry Wentland 
9944562236bSHarry Wentland bool resource_is_stream_unchanged(
995ab2541b6SAric Cyr 	const struct validate_context *old_context, const struct core_stream *stream)
9964562236bSHarry Wentland {
997ab2541b6SAric Cyr 	int i;
9984562236bSHarry Wentland 
999ab2541b6SAric Cyr 	for (i = 0; i < old_context->stream_count; i++) {
1000ab2541b6SAric Cyr 		const struct core_stream *old_stream = old_context->streams[i];
10014562236bSHarry Wentland 
10024562236bSHarry Wentland 		if (are_stream_backends_same(old_stream, stream))
10034562236bSHarry Wentland 				return true;
10044562236bSHarry Wentland 	}
10054562236bSHarry Wentland 
10064562236bSHarry Wentland 	return false;
10074562236bSHarry Wentland }
10084562236bSHarry Wentland 
10094562236bSHarry Wentland static void copy_pipe_ctx(
10104562236bSHarry Wentland 	const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
10114562236bSHarry Wentland {
10124562236bSHarry Wentland 	struct core_surface *surface = to_pipe_ctx->surface;
10134562236bSHarry Wentland 	struct core_stream *stream = to_pipe_ctx->stream;
10144562236bSHarry Wentland 
10154562236bSHarry Wentland 	*to_pipe_ctx = *from_pipe_ctx;
10164562236bSHarry Wentland 	to_pipe_ctx->stream = stream;
10174562236bSHarry Wentland 	if (surface != NULL)
10184562236bSHarry Wentland 		to_pipe_ctx->surface = surface;
10194562236bSHarry Wentland }
10204562236bSHarry Wentland 
10214562236bSHarry Wentland static struct core_stream *find_pll_sharable_stream(
10224562236bSHarry Wentland 		const struct core_stream *stream_needs_pll,
10234562236bSHarry Wentland 		struct validate_context *context)
10244562236bSHarry Wentland {
1025ab2541b6SAric Cyr 	int i;
10264562236bSHarry Wentland 
1027ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1028ab2541b6SAric Cyr 		struct core_stream *stream_has_pll = context->streams[i];
10294562236bSHarry Wentland 
10304562236bSHarry Wentland 		/* We are looking for non dp, non virtual stream */
10314562236bSHarry Wentland 		if (resource_are_streams_timing_synchronizable(
10324562236bSHarry Wentland 			stream_needs_pll, stream_has_pll)
10334562236bSHarry Wentland 			&& !dc_is_dp_signal(stream_has_pll->signal)
10344562236bSHarry Wentland 			&& stream_has_pll->sink->link->public.connector_signal
10354562236bSHarry Wentland 			!= SIGNAL_TYPE_VIRTUAL)
10364562236bSHarry Wentland 			return stream_has_pll;
1037ab2541b6SAric Cyr 
10384562236bSHarry Wentland 	}
10394562236bSHarry Wentland 
10404562236bSHarry Wentland 	return NULL;
10414562236bSHarry Wentland }
10424562236bSHarry Wentland 
10434562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
10444562236bSHarry Wentland {
10454562236bSHarry Wentland 	uint32_t pix_clk = timing->pix_clk_khz;
10464562236bSHarry Wentland 	uint32_t normalized_pix_clk = pix_clk;
10474562236bSHarry Wentland 
10484562236bSHarry Wentland 	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
10494562236bSHarry Wentland 		pix_clk /= 2;
1050cc4d99b8SCharlene Liu 	if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
10514562236bSHarry Wentland 		switch (timing->display_color_depth) {
10524562236bSHarry Wentland 		case COLOR_DEPTH_888:
10534562236bSHarry Wentland 			normalized_pix_clk = pix_clk;
10544562236bSHarry Wentland 			break;
10554562236bSHarry Wentland 		case COLOR_DEPTH_101010:
10564562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 30) / 24;
10574562236bSHarry Wentland 			break;
10584562236bSHarry Wentland 		case COLOR_DEPTH_121212:
10594562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 36) / 24;
10604562236bSHarry Wentland 		break;
10614562236bSHarry Wentland 		case COLOR_DEPTH_161616:
10624562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 48) / 24;
10634562236bSHarry Wentland 		break;
10644562236bSHarry Wentland 		default:
10654562236bSHarry Wentland 			ASSERT(0);
10664562236bSHarry Wentland 		break;
10674562236bSHarry Wentland 		}
1068cc4d99b8SCharlene Liu 	}
10694562236bSHarry Wentland 	return normalized_pix_clk;
10704562236bSHarry Wentland }
10714562236bSHarry Wentland 
10724562236bSHarry Wentland static void calculate_phy_pix_clks(
10734562236bSHarry Wentland 		const struct core_dc *dc,
10744562236bSHarry Wentland 		struct validate_context *context)
10754562236bSHarry Wentland {
1076ab2541b6SAric Cyr 	int i;
10774562236bSHarry Wentland 
1078ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1079ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
10804562236bSHarry Wentland 
10814562236bSHarry Wentland 		update_stream_signal(stream);
10824562236bSHarry Wentland 
10834562236bSHarry Wentland 		/* update actual pixel clock on all streams */
10844562236bSHarry Wentland 		if (dc_is_hdmi_signal(stream->signal))
10854562236bSHarry Wentland 			stream->phy_pix_clk = get_norm_pix_clk(
10864562236bSHarry Wentland 				&stream->public.timing);
10874562236bSHarry Wentland 		else
10884562236bSHarry Wentland 			stream->phy_pix_clk =
10894562236bSHarry Wentland 				stream->public.timing.pix_clk_khz;
10904562236bSHarry Wentland 	}
10914562236bSHarry Wentland }
10924562236bSHarry Wentland 
10934562236bSHarry Wentland enum dc_status resource_map_pool_resources(
10944562236bSHarry Wentland 		const struct core_dc *dc,
10954562236bSHarry Wentland 		struct validate_context *context)
10964562236bSHarry Wentland {
1097ab2541b6SAric Cyr 	int i, j;
10984562236bSHarry Wentland 
10994562236bSHarry Wentland 	calculate_phy_pix_clks(dc, context);
11004562236bSHarry Wentland 
1101ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1102ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
11034562236bSHarry Wentland 
11044b679bc3SCharlene Liu 		if (!resource_is_stream_unchanged(dc->current_context, stream)) {
11054b679bc3SCharlene Liu 			if (stream != NULL && dc->current_context->streams[i] != NULL) {
11064b679bc3SCharlene Liu 				stream->bit_depth_params =
11074b679bc3SCharlene Liu 						dc->current_context->streams[i]->bit_depth_params;
11084b679bc3SCharlene Liu 				stream->clamping = dc->current_context->streams[i]->clamping;
11094562236bSHarry Wentland 			continue;
11104b679bc3SCharlene Liu 		}
11114b679bc3SCharlene Liu 	}
11124562236bSHarry Wentland 		/* mark resources used for stream that is already active */
1113ab2541b6SAric Cyr 		for (j = 0; j < MAX_PIPES; j++) {
11144562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx =
1115ab2541b6SAric Cyr 				&context->res_ctx.pipe_ctx[j];
11164562236bSHarry Wentland 			const struct pipe_ctx *old_pipe_ctx =
1117ab2541b6SAric Cyr 				&dc->current_context->res_ctx.pipe_ctx[j];
11184562236bSHarry Wentland 
11194562236bSHarry Wentland 			if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
11204562236bSHarry Wentland 				continue;
11214562236bSHarry Wentland 
11224562236bSHarry Wentland 			pipe_ctx->stream = stream;
11234562236bSHarry Wentland 			copy_pipe_ctx(old_pipe_ctx, pipe_ctx);
11244562236bSHarry Wentland 
11258c737fccSYongqiang Sun 			/* Split pipe resource, do not acquire back end */
11268c737fccSYongqiang Sun 			if (!pipe_ctx->stream_enc)
11278c737fccSYongqiang Sun 				continue;
11288c737fccSYongqiang Sun 
11294562236bSHarry Wentland 			set_stream_engine_in_use(
11304562236bSHarry Wentland 				&context->res_ctx,
11314562236bSHarry Wentland 				pipe_ctx->stream_enc);
11324562236bSHarry Wentland 
11334562236bSHarry Wentland 			/* Switch to dp clock source only if there is
11344562236bSHarry Wentland 			 * no non dp stream that shares the same timing
11354562236bSHarry Wentland 			 * with the dp stream.
11364562236bSHarry Wentland 			 */
11374562236bSHarry Wentland 			if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
11384562236bSHarry Wentland 				!find_pll_sharable_stream(stream, context))
11394562236bSHarry Wentland 				pipe_ctx->clock_source =
11404562236bSHarry Wentland 					context->res_ctx.pool->dp_clock_source;
11414562236bSHarry Wentland 
11424562236bSHarry Wentland 			resource_reference_clock_source(
11434562236bSHarry Wentland 				&context->res_ctx,
11444562236bSHarry Wentland 				pipe_ctx->clock_source);
11454562236bSHarry Wentland 
11464562236bSHarry Wentland 			set_audio_in_use(&context->res_ctx,
11474562236bSHarry Wentland 					 pipe_ctx->audio);
11484562236bSHarry Wentland 		}
11494562236bSHarry Wentland 	}
11504562236bSHarry Wentland 
1151ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1152ab2541b6SAric Cyr 		struct core_stream *stream = context->streams[i];
11534562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx = NULL;
11544562236bSHarry Wentland 		int pipe_idx = -1;
11554562236bSHarry Wentland 
11564562236bSHarry Wentland 		if (resource_is_stream_unchanged(dc->current_context, stream))
11574562236bSHarry Wentland 			continue;
11584562236bSHarry Wentland 		/* acquire new resources */
1159ab2541b6SAric Cyr 		pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream);
11604562236bSHarry Wentland 		if (pipe_idx < 0)
11614562236bSHarry Wentland 			return DC_NO_CONTROLLER_RESOURCE;
11624562236bSHarry Wentland 
11634562236bSHarry Wentland 
11644562236bSHarry Wentland 		pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
11654562236bSHarry Wentland 
11664562236bSHarry Wentland 		pipe_ctx->stream_enc =
11674562236bSHarry Wentland 			find_first_free_match_stream_enc_for_link(
11684562236bSHarry Wentland 				&context->res_ctx, stream);
11694562236bSHarry Wentland 
11704562236bSHarry Wentland 		if (!pipe_ctx->stream_enc)
11714562236bSHarry Wentland 			return DC_NO_STREAM_ENG_RESOURCE;
11724562236bSHarry Wentland 
11734562236bSHarry Wentland 		set_stream_engine_in_use(
11744562236bSHarry Wentland 			&context->res_ctx,
11754562236bSHarry Wentland 			pipe_ctx->stream_enc);
11764562236bSHarry Wentland 
11774562236bSHarry Wentland 		/* TODO: Add check if ASIC support and EDID audio */
11784562236bSHarry Wentland 		if (!stream->sink->converter_disable_audio &&
11794562236bSHarry Wentland 			dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
11804562236bSHarry Wentland 			stream->public.audio_info.mode_count) {
11814562236bSHarry Wentland 			pipe_ctx->audio = find_first_free_audio(
11824562236bSHarry Wentland 				&context->res_ctx);
11834562236bSHarry Wentland 
11844562236bSHarry Wentland 			/*
11854562236bSHarry Wentland 			 * Audio assigned in order first come first get.
11864562236bSHarry Wentland 			 * There are asics which has number of audio
11874562236bSHarry Wentland 			 * resources less then number of pipes
11884562236bSHarry Wentland 			 */
11894562236bSHarry Wentland 			if (pipe_ctx->audio)
11904562236bSHarry Wentland 				set_audio_in_use(
11914562236bSHarry Wentland 					&context->res_ctx,
11924562236bSHarry Wentland 					pipe_ctx->audio);
11934562236bSHarry Wentland 		}
11944562236bSHarry Wentland 
1195ab2541b6SAric Cyr 		context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst;
11964562236bSHarry Wentland 	}
11974562236bSHarry Wentland 
11984562236bSHarry Wentland 	return DC_OK;
11994562236bSHarry Wentland }
12004562236bSHarry Wentland 
1201ab2541b6SAric Cyr /* first stream in the context is used to populate the rest */
1202ab2541b6SAric Cyr void validate_guaranteed_copy_streams(
12034562236bSHarry Wentland 		struct validate_context *context,
1204ab2541b6SAric Cyr 		int max_streams)
12054562236bSHarry Wentland {
12064562236bSHarry Wentland 	int i;
12074562236bSHarry Wentland 
1208ab2541b6SAric Cyr 	for (i = 1; i < max_streams; i++) {
1209ab2541b6SAric Cyr 		context->streams[i] = context->streams[0];
12104562236bSHarry Wentland 
12114562236bSHarry Wentland 		copy_pipe_ctx(&context->res_ctx.pipe_ctx[0],
12124562236bSHarry Wentland 			      &context->res_ctx.pipe_ctx[i]);
12134562236bSHarry Wentland 		context->res_ctx.pipe_ctx[i].stream =
12144562236bSHarry Wentland 				context->res_ctx.pipe_ctx[0].stream;
12154562236bSHarry Wentland 
1216ab2541b6SAric Cyr 		dc_stream_retain(&context->streams[i]->public);
1217ab2541b6SAric Cyr 		context->stream_count++;
12184562236bSHarry Wentland 	}
12194562236bSHarry Wentland }
12204562236bSHarry Wentland 
12216e4d6beeSTony Cheng static void patch_gamut_packet_checksum(
12226e4d6beeSTony Cheng 		struct encoder_info_packet *gamut_packet)
12234562236bSHarry Wentland {
12244562236bSHarry Wentland 	/* For gamut we recalc checksum */
12256e4d6beeSTony Cheng 	if (gamut_packet->valid) {
12264562236bSHarry Wentland 		uint8_t chk_sum = 0;
12274562236bSHarry Wentland 		uint8_t *ptr;
12284562236bSHarry Wentland 		uint8_t i;
12294562236bSHarry Wentland 
12304562236bSHarry Wentland 		/*start of the Gamut data. */
12316e4d6beeSTony Cheng 		ptr = &gamut_packet->sb[3];
12324562236bSHarry Wentland 
12336e4d6beeSTony Cheng 		for (i = 0; i <= gamut_packet->sb[1]; i++)
12344562236bSHarry Wentland 			chk_sum += ptr[i];
12354562236bSHarry Wentland 
12366e4d6beeSTony Cheng 		gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
12371646a6feSAndrew Wong 	}
12384562236bSHarry Wentland }
12394562236bSHarry Wentland 
12404562236bSHarry Wentland static void set_avi_info_frame(
12416e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
12424562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
12434562236bSHarry Wentland {
12444562236bSHarry Wentland 	struct core_stream *stream = pipe_ctx->stream;
12454562236bSHarry Wentland 	enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
12464562236bSHarry Wentland 	struct info_frame info_frame = { {0} };
12474562236bSHarry Wentland 	uint32_t pixel_encoding = 0;
12484562236bSHarry Wentland 	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
12494562236bSHarry Wentland 	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
12504562236bSHarry Wentland 	bool itc = false;
12514562236bSHarry Wentland 	uint8_t cn0_cn1 = 0;
12524562236bSHarry Wentland 	uint8_t *check_sum = NULL;
12534562236bSHarry Wentland 	uint8_t byte_index = 0;
12544562236bSHarry Wentland 
12554562236bSHarry Wentland 	color_space = pipe_ctx->stream->public.output_color_space;
12564562236bSHarry Wentland 
12574562236bSHarry Wentland 	/* Initialize header */
12584562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.
12593e183c5fSDave Airlie 			info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
12604562236bSHarry Wentland 	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
12614562236bSHarry Wentland 	* not be used in HDMI 2.0 (Section 10.1) */
12623e183c5fSDave Airlie 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2;
12634562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.header.length =
12643e183c5fSDave Airlie 			HDMI_AVI_INFOFRAME_SIZE;
12654562236bSHarry Wentland 
12664562236bSHarry Wentland 	/*
12674562236bSHarry Wentland 	 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
12684562236bSHarry Wentland 	 * according to HDMI 2.0 spec (Section 10.1)
12694562236bSHarry Wentland 	 */
12704562236bSHarry Wentland 
12714562236bSHarry Wentland 	switch (stream->public.timing.pixel_encoding) {
12724562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR422:
12734562236bSHarry Wentland 		pixel_encoding = 1;
12744562236bSHarry Wentland 		break;
12754562236bSHarry Wentland 
12764562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR444:
12774562236bSHarry Wentland 		pixel_encoding = 2;
12784562236bSHarry Wentland 		break;
12794562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR420:
12804562236bSHarry Wentland 		pixel_encoding = 3;
12814562236bSHarry Wentland 		break;
12824562236bSHarry Wentland 
12834562236bSHarry Wentland 	case PIXEL_ENCODING_RGB:
12844562236bSHarry Wentland 	default:
12854562236bSHarry Wentland 		pixel_encoding = 0;
12864562236bSHarry Wentland 	}
12874562236bSHarry Wentland 
12884562236bSHarry Wentland 	/* Y0_Y1_Y2 : The pixel encoding */
12894562236bSHarry Wentland 	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
12904562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 =
12914562236bSHarry Wentland 		pixel_encoding;
12924562236bSHarry Wentland 
12934562236bSHarry Wentland 	/* A0 = 1 Active Format Information valid */
12944562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.A0 =
12954562236bSHarry Wentland 		ACTIVE_FORMAT_VALID;
12964562236bSHarry Wentland 
12974562236bSHarry Wentland 	/* B0, B1 = 3; Bar info data is valid */
12984562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 =
12994562236bSHarry Wentland 		BAR_INFO_BOTH_VALID;
13004562236bSHarry Wentland 
13014562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 =
13024562236bSHarry Wentland 			PICTURE_SCALING_UNIFORM;
13034562236bSHarry Wentland 
13044562236bSHarry Wentland 	/* S0, S1 : Underscan / Overscan */
13054562236bSHarry Wentland 	/* TODO: un-hardcode scan type */
13064562236bSHarry Wentland 	scan_type = SCANNING_TYPE_UNDERSCAN;
13074562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type;
13084562236bSHarry Wentland 
13094562236bSHarry Wentland 	/* C0, C1 : Colorimetry */
13108fde5884SCharlene Liu 	if (color_space == COLOR_SPACE_YCBCR709 ||
13118fde5884SCharlene Liu 			color_space == COLOR_SPACE_YCBCR709_LIMITED)
13124562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13134562236bSHarry Wentland 				COLORIMETRY_ITU709;
13148fde5884SCharlene Liu 	else if (color_space == COLOR_SPACE_YCBCR601 ||
13158fde5884SCharlene Liu 			color_space == COLOR_SPACE_YCBCR601_LIMITED)
13164562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13174562236bSHarry Wentland 				COLORIMETRY_ITU601;
13188fde5884SCharlene Liu 	else {
13198fde5884SCharlene Liu 		if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB)
13208fde5884SCharlene Liu 			BREAK_TO_DEBUGGER();
13214562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
13224562236bSHarry Wentland 				COLORIMETRY_NO_DATA;
13238fde5884SCharlene Liu 	}
1324534db198SAmy Zhang 	if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
1325534db198SAmy Zhang 			color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
1326534db198SAmy Zhang 			color_space == COLOR_SPACE_2020_YCBCR) {
1327534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
1328534db198SAmy Zhang 				COLORIMETRYEX_BT2020RGBYCBCR;
1329534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1330534db198SAmy Zhang 				COLORIMETRY_EXTENDED;
1331534db198SAmy Zhang 	} else if (color_space == COLOR_SPACE_ADOBERGB) {
1332534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
1333534db198SAmy Zhang 				COLORIMETRYEX_ADOBERGB;
1334534db198SAmy Zhang 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1335534db198SAmy Zhang 				COLORIMETRY_EXTENDED;
1336534db198SAmy Zhang 	}
1337534db198SAmy Zhang 
13384562236bSHarry Wentland 	/* TODO: un-hardcode aspect ratio */
13394562236bSHarry Wentland 	aspect = stream->public.timing.aspect_ratio;
13404562236bSHarry Wentland 
13414562236bSHarry Wentland 	switch (aspect) {
13424562236bSHarry Wentland 	case ASPECT_RATIO_4_3:
13434562236bSHarry Wentland 	case ASPECT_RATIO_16_9:
13444562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect;
13454562236bSHarry Wentland 		break;
13464562236bSHarry Wentland 
13474562236bSHarry Wentland 	case ASPECT_RATIO_NO_DATA:
13484562236bSHarry Wentland 	case ASPECT_RATIO_64_27:
13494562236bSHarry Wentland 	case ASPECT_RATIO_256_135:
13504562236bSHarry Wentland 	default:
13514562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0;
13524562236bSHarry Wentland 	}
13534562236bSHarry Wentland 
13544562236bSHarry Wentland 	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
13554562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 =
13564562236bSHarry Wentland 			ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
13574562236bSHarry Wentland 
13584562236bSHarry Wentland 	/* TODO: un-hardcode cn0_cn1 and itc */
13594562236bSHarry Wentland 	cn0_cn1 = 0;
13604562236bSHarry Wentland 	itc = false;
13614562236bSHarry Wentland 
13624562236bSHarry Wentland 	if (itc) {
13634562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1;
13644562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 =
13654562236bSHarry Wentland 			cn0_cn1;
13664562236bSHarry Wentland 	}
13674562236bSHarry Wentland 
13684562236bSHarry Wentland 	/* TODO : We should handle YCC quantization */
13694562236bSHarry Wentland 	/* but we do not have matrix calculation */
13704562236bSHarry Wentland 	if (color_space == COLOR_SPACE_SRGB) {
13714562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
13724562236bSHarry Wentland 						RGB_QUANTIZATION_FULL_RANGE;
13734562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
13744562236bSHarry Wentland 						YYC_QUANTIZATION_FULL_RANGE;
13754562236bSHarry Wentland 	} else if (color_space == COLOR_SPACE_SRGB_LIMITED) {
13764562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
13774562236bSHarry Wentland 						RGB_QUANTIZATION_LIMITED_RANGE;
13784562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
13794562236bSHarry Wentland 						YYC_QUANTIZATION_LIMITED_RANGE;
13804562236bSHarry Wentland 	} else {
13814562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
13824562236bSHarry Wentland 						RGB_QUANTIZATION_DEFAULT_RANGE;
13834562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
13844562236bSHarry Wentland 						YYC_QUANTIZATION_LIMITED_RANGE;
13854562236bSHarry Wentland 	}
13864562236bSHarry Wentland 
13874562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 =
13884562236bSHarry Wentland 					stream->public.timing.vic;
13894562236bSHarry Wentland 
13904562236bSHarry Wentland 	/* pixel repetition
13914562236bSHarry Wentland 	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
13924562236bSHarry Wentland 	 * repetition start from 1 */
13934562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0;
13944562236bSHarry Wentland 
13954562236bSHarry Wentland 	/* Bar Info
13964562236bSHarry Wentland 	 * barTop:    Line Number of End of Top Bar.
13974562236bSHarry Wentland 	 * barBottom: Line Number of Start of Bottom Bar.
13984562236bSHarry Wentland 	 * barLeft:   Pixel Number of End of Left Bar.
13994562236bSHarry Wentland 	 * barRight:  Pixel Number of Start of Right Bar. */
14004562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top =
14014562236bSHarry Wentland 			stream->public.timing.v_border_top;
14024562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom =
14034562236bSHarry Wentland 		(stream->public.timing.v_border_top
14044562236bSHarry Wentland 			- stream->public.timing.v_border_bottom + 1);
14054562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left =
14064562236bSHarry Wentland 			stream->public.timing.h_border_left;
14074562236bSHarry Wentland 	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right =
14084562236bSHarry Wentland 		(stream->public.timing.h_total
14094562236bSHarry Wentland 			- stream->public.timing.h_border_right + 1);
14104562236bSHarry Wentland 
14114562236bSHarry Wentland 	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
14124562236bSHarry Wentland 	check_sum =
14134562236bSHarry Wentland 		&info_frame.
14144562236bSHarry Wentland 		avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
14153e183c5fSDave Airlie 	*check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2;
14164562236bSHarry Wentland 
14173e183c5fSDave Airlie 	for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++)
14184562236bSHarry Wentland 		*check_sum += info_frame.avi_info_packet.info_packet_hdmi.
14194562236bSHarry Wentland 				packet_raw_data.sb[byte_index];
14204562236bSHarry Wentland 
14214562236bSHarry Wentland 	/* one byte complement */
14224562236bSHarry Wentland 	*check_sum = (uint8_t) (0x100 - *check_sum);
14234562236bSHarry Wentland 
14244562236bSHarry Wentland 	/* Store in hw_path_mode */
14254562236bSHarry Wentland 	info_packet->hb0 =
14264562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0;
14274562236bSHarry Wentland 	info_packet->hb1 =
14284562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1;
14294562236bSHarry Wentland 	info_packet->hb2 =
14304562236bSHarry Wentland 		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2;
14314562236bSHarry Wentland 
1432e66e4d64SHarry Wentland 	for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet.
1433e66e4d64SHarry Wentland 				info_packet_hdmi.packet_raw_data.sb); byte_index++)
14344562236bSHarry Wentland 		info_packet->sb[byte_index] = info_frame.avi_info_packet.
14354562236bSHarry Wentland 				info_packet_hdmi.packet_raw_data.sb[byte_index];
14364562236bSHarry Wentland 
14374562236bSHarry Wentland 	info_packet->valid = true;
14384562236bSHarry Wentland }
14394562236bSHarry Wentland 
14406e4d6beeSTony Cheng static void set_vendor_info_packet(
14416e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
14426e4d6beeSTony Cheng 		struct core_stream *stream)
14434562236bSHarry Wentland {
14444562236bSHarry Wentland 	uint32_t length = 0;
14454562236bSHarry Wentland 	bool hdmi_vic_mode = false;
14464562236bSHarry Wentland 	uint8_t checksum = 0;
14474562236bSHarry Wentland 	uint32_t i = 0;
14484562236bSHarry Wentland 	enum dc_timing_3d_format format;
14494562236bSHarry Wentland 
14504562236bSHarry Wentland 	format = stream->public.timing.timing_3d_format;
14514562236bSHarry Wentland 
14524562236bSHarry Wentland 	/* Can be different depending on packet content */
14534562236bSHarry Wentland 	length = 5;
14544562236bSHarry Wentland 
14554562236bSHarry Wentland 	if (stream->public.timing.hdmi_vic != 0
14564562236bSHarry Wentland 			&& stream->public.timing.h_total >= 3840
14574562236bSHarry Wentland 			&& stream->public.timing.v_total >= 2160)
14584562236bSHarry Wentland 		hdmi_vic_mode = true;
14594562236bSHarry Wentland 
14604562236bSHarry Wentland 	/* According to HDMI 1.4a CTS, VSIF should be sent
14614562236bSHarry Wentland 	 * for both 3D stereo and HDMI VIC modes.
14624562236bSHarry Wentland 	 * For all other modes, there is no VSIF sent.  */
14634562236bSHarry Wentland 
14644562236bSHarry Wentland 	if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
14654562236bSHarry Wentland 		return;
14664562236bSHarry Wentland 
14674562236bSHarry Wentland 	/* 24bit IEEE Registration identifier (0x000c03). LSB first. */
14684562236bSHarry Wentland 	info_packet->sb[1] = 0x03;
14694562236bSHarry Wentland 	info_packet->sb[2] = 0x0C;
14704562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
14714562236bSHarry Wentland 
14724562236bSHarry Wentland 	/*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
14734562236bSHarry Wentland 	 * The value for HDMI_Video_Format are:
14744562236bSHarry Wentland 	 * 0x0 (0b000) - No additional HDMI video format is presented in this
14754562236bSHarry Wentland 	 * packet
14764562236bSHarry Wentland 	 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
14774562236bSHarry Wentland 	 * parameter follows
14784562236bSHarry Wentland 	 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
14794562236bSHarry Wentland 	 * potentially 3D_Ext_Data follows
14804562236bSHarry Wentland 	 * 0x3..0x7 (0b011..0b111) - reserved for future use */
14814562236bSHarry Wentland 	if (format != TIMING_3D_FORMAT_NONE)
14824562236bSHarry Wentland 		info_packet->sb[4] = (2 << 5);
14834562236bSHarry Wentland 	else if (hdmi_vic_mode)
14844562236bSHarry Wentland 		info_packet->sb[4] = (1 << 5);
14854562236bSHarry Wentland 
14864562236bSHarry Wentland 	/* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
14874562236bSHarry Wentland 	 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
14884562236bSHarry Wentland 	 * The value for 3D_Structure are:
14894562236bSHarry Wentland 	 * 0x0 - Frame Packing
14904562236bSHarry Wentland 	 * 0x1 - Field Alternative
14914562236bSHarry Wentland 	 * 0x2 - Line Alternative
14924562236bSHarry Wentland 	 * 0x3 - Side-by-Side (full)
14934562236bSHarry Wentland 	 * 0x4 - L + depth
14944562236bSHarry Wentland 	 * 0x5 - L + depth + graphics + graphics-depth
14954562236bSHarry Wentland 	 * 0x6 - Top-and-Bottom
14964562236bSHarry Wentland 	 * 0x7 - Reserved for future use
14974562236bSHarry Wentland 	 * 0x8 - Side-by-Side (Half)
14984562236bSHarry Wentland 	 * 0x9..0xE - Reserved for future use
14994562236bSHarry Wentland 	 * 0xF - Not used */
15004562236bSHarry Wentland 	switch (format) {
15014562236bSHarry Wentland 	case TIMING_3D_FORMAT_HW_FRAME_PACKING:
15024562236bSHarry Wentland 	case TIMING_3D_FORMAT_SW_FRAME_PACKING:
15034562236bSHarry Wentland 		info_packet->sb[5] = (0x0 << 4);
15044562236bSHarry Wentland 		break;
15054562236bSHarry Wentland 
15064562236bSHarry Wentland 	case TIMING_3D_FORMAT_SIDE_BY_SIDE:
15074562236bSHarry Wentland 	case TIMING_3D_FORMAT_SBS_SW_PACKED:
15084562236bSHarry Wentland 		info_packet->sb[5] = (0x8 << 4);
15094562236bSHarry Wentland 		length = 6;
15104562236bSHarry Wentland 		break;
15114562236bSHarry Wentland 
15124562236bSHarry Wentland 	case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
15134562236bSHarry Wentland 	case TIMING_3D_FORMAT_TB_SW_PACKED:
15144562236bSHarry Wentland 		info_packet->sb[5] = (0x6 << 4);
15154562236bSHarry Wentland 		break;
15164562236bSHarry Wentland 
15174562236bSHarry Wentland 	default:
15184562236bSHarry Wentland 		break;
15194562236bSHarry Wentland 	}
15204562236bSHarry Wentland 
15214562236bSHarry Wentland 	/*PB5: If PB4 is set to 0x1 (extended resolution format)
15224562236bSHarry Wentland 	 * fill PB5 with the correct HDMI VIC code */
15234562236bSHarry Wentland 	if (hdmi_vic_mode)
15244562236bSHarry Wentland 		info_packet->sb[5] = stream->public.timing.hdmi_vic;
15254562236bSHarry Wentland 
15264562236bSHarry Wentland 	/* Header */
15273e183c5fSDave Airlie 	info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */
15284562236bSHarry Wentland 	info_packet->hb1 = 0x01; /* Version */
15294562236bSHarry Wentland 
15304562236bSHarry Wentland 	/* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
15314562236bSHarry Wentland 	info_packet->hb2 = (uint8_t) (length);
15324562236bSHarry Wentland 
15334562236bSHarry Wentland 	/* Calculate checksum */
15344562236bSHarry Wentland 	checksum = 0;
15354562236bSHarry Wentland 	checksum += info_packet->hb0;
15364562236bSHarry Wentland 	checksum += info_packet->hb1;
15374562236bSHarry Wentland 	checksum += info_packet->hb2;
15384562236bSHarry Wentland 
15394562236bSHarry Wentland 	for (i = 1; i <= length; i++)
15404562236bSHarry Wentland 		checksum += info_packet->sb[i];
15414562236bSHarry Wentland 
15424562236bSHarry Wentland 	info_packet->sb[0] = (uint8_t) (0x100 - checksum);
15434562236bSHarry Wentland 
15444562236bSHarry Wentland 	info_packet->valid = true;
15454562236bSHarry Wentland }
15464562236bSHarry Wentland 
15476e4d6beeSTony Cheng static void set_spd_info_packet(
15486e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
15496e4d6beeSTony Cheng 		struct core_stream *stream)
15504562236bSHarry Wentland {
15514562236bSHarry Wentland 	/* SPD info packet for FreeSync */
15524562236bSHarry Wentland 
15534562236bSHarry Wentland 	unsigned char checksum = 0;
15544562236bSHarry Wentland 	unsigned int idx, payload_size = 0;
15554562236bSHarry Wentland 
15564562236bSHarry Wentland 	/* Check if Freesync is supported. Return if false. If true,
15574562236bSHarry Wentland 	 * set the corresponding bit in the info packet
15584562236bSHarry Wentland 	 */
15594562236bSHarry Wentland 	if (stream->public.freesync_ctx.supported == false)
15604562236bSHarry Wentland 		return;
15614562236bSHarry Wentland 
15624562236bSHarry Wentland 	if (dc_is_hdmi_signal(stream->signal)) {
15634562236bSHarry Wentland 
15644562236bSHarry Wentland 		/* HEADER */
15654562236bSHarry Wentland 
15664562236bSHarry Wentland 		/* HB0  = Packet Type = 0x83 (Source Product
15674562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
15684562236bSHarry Wentland 		 */
15693e183c5fSDave Airlie 		info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD;
15704562236bSHarry Wentland 
15714562236bSHarry Wentland 		/* HB1  = Version = 0x01 */
15724562236bSHarry Wentland 		info_packet->hb1 = 0x01;
15734562236bSHarry Wentland 
15744562236bSHarry Wentland 		/* HB2  = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
15754562236bSHarry Wentland 		info_packet->hb2 = 0x08;
15764562236bSHarry Wentland 
15774562236bSHarry Wentland 		payload_size = 0x08;
15784562236bSHarry Wentland 
15794562236bSHarry Wentland 	} else if (dc_is_dp_signal(stream->signal)) {
15804562236bSHarry Wentland 
15814562236bSHarry Wentland 		/* HEADER */
15824562236bSHarry Wentland 
15834562236bSHarry Wentland 		/* HB0  = Secondary-data Packet ID = 0 - Only non-zero
15844562236bSHarry Wentland 		 *	  when used to associate audio related info packets
15854562236bSHarry Wentland 		 */
15864562236bSHarry Wentland 		info_packet->hb0 = 0x00;
15874562236bSHarry Wentland 
15884562236bSHarry Wentland 		/* HB1  = Packet Type = 0x83 (Source Product
15894562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
15904562236bSHarry Wentland 		 */
15913e183c5fSDave Airlie 		info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD;
15924562236bSHarry Wentland 
15934562236bSHarry Wentland 		/* HB2  = [Bits 7:0 = Least significant eight bits -
15944562236bSHarry Wentland 		 *	  For INFOFRAME, the value must be 1Bh]
15954562236bSHarry Wentland 		 */
15964562236bSHarry Wentland 		info_packet->hb2 = 0x1B;
15974562236bSHarry Wentland 
15984562236bSHarry Wentland 		/* HB3  = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
15994562236bSHarry Wentland 		 *	  [Bits 1:0 = Most significant two bits = 0x00]
16004562236bSHarry Wentland 		 */
16014562236bSHarry Wentland 		info_packet->hb3 = 0x04;
16024562236bSHarry Wentland 
16034562236bSHarry Wentland 		payload_size = 0x1B;
16044562236bSHarry Wentland 	}
16054562236bSHarry Wentland 
16064562236bSHarry Wentland 	/* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
16074562236bSHarry Wentland 	info_packet->sb[1] = 0x1A;
16084562236bSHarry Wentland 
16094562236bSHarry Wentland 	/* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
16104562236bSHarry Wentland 	info_packet->sb[2] = 0x00;
16114562236bSHarry Wentland 
16124562236bSHarry Wentland 	/* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
16134562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
16144562236bSHarry Wentland 
16154562236bSHarry Wentland 	/* PB4 = Reserved */
16164562236bSHarry Wentland 	info_packet->sb[4] = 0x00;
16174562236bSHarry Wentland 
16184562236bSHarry Wentland 	/* PB5 = Reserved */
16194562236bSHarry Wentland 	info_packet->sb[5] = 0x00;
16204562236bSHarry Wentland 
16214562236bSHarry Wentland 	/* PB6 = [Bits 7:3 = Reserved] */
16224562236bSHarry Wentland 	info_packet->sb[6] = 0x00;
16234562236bSHarry Wentland 
16244562236bSHarry Wentland 	if (stream->public.freesync_ctx.supported == true)
16254562236bSHarry Wentland 		/* PB6 = [Bit 0 = FreeSync Supported] */
16264562236bSHarry Wentland 		info_packet->sb[6] |= 0x01;
16274562236bSHarry Wentland 
16284562236bSHarry Wentland 	if (stream->public.freesync_ctx.enabled == true)
16294562236bSHarry Wentland 		/* PB6 = [Bit 1 = FreeSync Enabled] */
16304562236bSHarry Wentland 		info_packet->sb[6] |= 0x02;
16314562236bSHarry Wentland 
16324562236bSHarry Wentland 	if (stream->public.freesync_ctx.active == true)
16334562236bSHarry Wentland 		/* PB6 = [Bit 2 = FreeSync Active] */
16344562236bSHarry Wentland 		info_packet->sb[6] |= 0x04;
16354562236bSHarry Wentland 
16364562236bSHarry Wentland 	/* PB7 = FreeSync Minimum refresh rate (Hz) */
16374562236bSHarry Wentland 	info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx.
16384562236bSHarry Wentland 			min_refresh_in_micro_hz / 1000000);
16394562236bSHarry Wentland 
16404562236bSHarry Wentland 	/* PB8 = FreeSync Maximum refresh rate (Hz)
16414562236bSHarry Wentland 	 *
16424562236bSHarry Wentland 	 * Note: We do not use the maximum capable refresh rate
16434562236bSHarry Wentland 	 * of the panel, because we should never go above the field
16444562236bSHarry Wentland 	 * rate of the mode timing set.
16454562236bSHarry Wentland 	 */
16464562236bSHarry Wentland 	info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx.
16474562236bSHarry Wentland 			nominal_refresh_in_micro_hz / 1000000);
16484562236bSHarry Wentland 
16494562236bSHarry Wentland 	/* PB9 - PB27  = Reserved */
16504562236bSHarry Wentland 	for (idx = 9; idx <= 27; idx++)
16514562236bSHarry Wentland 		info_packet->sb[idx] = 0x00;
16524562236bSHarry Wentland 
16534562236bSHarry Wentland 	/* Calculate checksum */
16544562236bSHarry Wentland 	checksum += info_packet->hb0;
16554562236bSHarry Wentland 	checksum += info_packet->hb1;
16564562236bSHarry Wentland 	checksum += info_packet->hb2;
16574562236bSHarry Wentland 	checksum += info_packet->hb3;
16584562236bSHarry Wentland 
16594562236bSHarry Wentland 	for (idx = 1; idx <= payload_size; idx++)
16604562236bSHarry Wentland 		checksum += info_packet->sb[idx];
16614562236bSHarry Wentland 
16624562236bSHarry Wentland 	/* PB0 = Checksum (one byte complement) */
16634562236bSHarry Wentland 	info_packet->sb[0] = (unsigned char) (0x100 - checksum);
16644562236bSHarry Wentland 
16654562236bSHarry Wentland 	info_packet->valid = true;
16664562236bSHarry Wentland }
16674562236bSHarry Wentland 
16681646a6feSAndrew Wong static void set_hdr_static_info_packet(
16696e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
16701646a6feSAndrew Wong 		struct core_surface *surface,
16716e4d6beeSTony Cheng 		struct core_stream *stream)
16721646a6feSAndrew Wong {
1673e5cf325bSHarry Wentland 	uint16_t i = 0;
16741646a6feSAndrew Wong 	enum signal_type signal = stream->signal;
1675e5cf325bSHarry Wentland 	struct dc_hdr_static_metadata hdr_metadata;
1676e5cf325bSHarry Wentland 	uint32_t data;
16771646a6feSAndrew Wong 
16781646a6feSAndrew Wong 	if (!surface)
16791646a6feSAndrew Wong 		return;
16801646a6feSAndrew Wong 
1681e5cf325bSHarry Wentland 	hdr_metadata = surface->public.hdr_static_ctx;
16821646a6feSAndrew Wong 
168370063a59SAmy Zhang 	if (!hdr_metadata.hdr_supported)
168410bff005SYongqiang Sun 		return;
168510bff005SYongqiang Sun 
16861646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
16871646a6feSAndrew Wong 		info_packet->valid = true;
16881646a6feSAndrew Wong 
16891646a6feSAndrew Wong 		info_packet->hb0 = 0x87;
16901646a6feSAndrew Wong 		info_packet->hb1 = 0x01;
16911646a6feSAndrew Wong 		info_packet->hb2 = 0x1A;
16921646a6feSAndrew Wong 		i = 1;
16931646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
16941646a6feSAndrew Wong 		info_packet->valid = true;
16951646a6feSAndrew Wong 
16961646a6feSAndrew Wong 		info_packet->hb0 = 0x00;
16971646a6feSAndrew Wong 		info_packet->hb1 = 0x87;
16981646a6feSAndrew Wong 		info_packet->hb2 = 0x1D;
16991646a6feSAndrew Wong 		info_packet->hb3 = (0x13 << 2);
17001646a6feSAndrew Wong 		i = 2;
17011646a6feSAndrew Wong 	}
17021646a6feSAndrew Wong 
17031646a6feSAndrew Wong 	data = hdr_metadata.is_hdr;
17041646a6feSAndrew Wong 	info_packet->sb[i++] = data ? 0x02 : 0x00;
17051646a6feSAndrew Wong 	info_packet->sb[i++] = 0x00;
17061646a6feSAndrew Wong 
17071646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_x / 2;
17081646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17091646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17101646a6feSAndrew Wong 
17111646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_y / 2;
17121646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17131646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17141646a6feSAndrew Wong 
17151646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_x / 2;
17161646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17171646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17181646a6feSAndrew Wong 
17191646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_y / 2;
17201646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17211646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17221646a6feSAndrew Wong 
17231646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_x / 2;
17241646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17251646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17261646a6feSAndrew Wong 
17271646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_y / 2;
17281646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17291646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17301646a6feSAndrew Wong 
17311646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_x / 2;
17321646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17331646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17341646a6feSAndrew Wong 
17351646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_y / 2;
17361646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17371646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17381646a6feSAndrew Wong 
17391646a6feSAndrew Wong 	data = hdr_metadata.max_luminance;
17401646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17411646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17421646a6feSAndrew Wong 
17431646a6feSAndrew Wong 	data = hdr_metadata.min_luminance;
17441646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17451646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17461646a6feSAndrew Wong 
17471646a6feSAndrew Wong 	data = hdr_metadata.maximum_content_light_level;
17481646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17491646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17501646a6feSAndrew Wong 
17511646a6feSAndrew Wong 	data = hdr_metadata.maximum_frame_average_light_level;
17521646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
17531646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
17541646a6feSAndrew Wong 
17551646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
17561646a6feSAndrew Wong 		uint32_t checksum = 0;
17571646a6feSAndrew Wong 
17581646a6feSAndrew Wong 		checksum += info_packet->hb0;
17591646a6feSAndrew Wong 		checksum += info_packet->hb1;
17601646a6feSAndrew Wong 		checksum += info_packet->hb2;
17611646a6feSAndrew Wong 
17621646a6feSAndrew Wong 		for (i = 1; i <= info_packet->hb2; i++)
17631646a6feSAndrew Wong 			checksum += info_packet->sb[i];
17641646a6feSAndrew Wong 
17651646a6feSAndrew Wong 		info_packet->sb[0] = 0x100 - checksum;
17661646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
17671646a6feSAndrew Wong 		info_packet->sb[0] = 0x01;
17681646a6feSAndrew Wong 		info_packet->sb[1] = 0x1A;
17691646a6feSAndrew Wong 	}
17701646a6feSAndrew Wong }
17711646a6feSAndrew Wong 
17726e4d6beeSTony Cheng static void set_vsc_info_packet(
17736e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
17746e4d6beeSTony Cheng 		struct core_stream *stream)
17754562236bSHarry Wentland {
17764562236bSHarry Wentland 	unsigned int vscPacketRevision = 0;
17774562236bSHarry Wentland 	unsigned int i;
17784562236bSHarry Wentland 
17794562236bSHarry Wentland 	if (stream->sink->link->public.psr_caps.psr_version != 0) {
17804562236bSHarry Wentland 		vscPacketRevision = 2;
17814562236bSHarry Wentland 	}
17824562236bSHarry Wentland 
17834562236bSHarry Wentland 	/* VSC packet not needed based on the features
17844562236bSHarry Wentland 	 * supported by this DP display
17854562236bSHarry Wentland 	 */
17864562236bSHarry Wentland 	if (vscPacketRevision == 0)
17874562236bSHarry Wentland 		return;
17884562236bSHarry Wentland 
17894562236bSHarry Wentland 	if (vscPacketRevision == 0x2) {
17904562236bSHarry Wentland 		/* Secondary-data Packet ID = 0*/
17914562236bSHarry Wentland 		info_packet->hb0 = 0x00;
17924562236bSHarry Wentland 		/* 07h - Packet Type Value indicating Video
17934562236bSHarry Wentland 		 * Stream Configuration packet
17944562236bSHarry Wentland 		 */
17954562236bSHarry Wentland 		info_packet->hb1 = 0x07;
17964562236bSHarry Wentland 		/* 02h = VSC SDP supporting 3D stereo and PSR
17974562236bSHarry Wentland 		 * (applies to eDP v1.3 or higher).
17984562236bSHarry Wentland 		 */
17994562236bSHarry Wentland 		info_packet->hb2 = 0x02;
18004562236bSHarry Wentland 		/* 08h = VSC packet supporting 3D stereo + PSR
18014562236bSHarry Wentland 		 * (HB2 = 02h).
18024562236bSHarry Wentland 		 */
18034562236bSHarry Wentland 		info_packet->hb3 = 0x08;
18044562236bSHarry Wentland 
18054562236bSHarry Wentland 		for (i = 0; i < 28; i++)
18064562236bSHarry Wentland 			info_packet->sb[i] = 0;
18074562236bSHarry Wentland 
18084562236bSHarry Wentland 		info_packet->valid = true;
18094562236bSHarry Wentland 	}
18104562236bSHarry Wentland 
18114562236bSHarry Wentland 	/*TODO: stereo 3D support and extend pixel encoding colorimetry*/
18124562236bSHarry Wentland }
18134562236bSHarry Wentland 
18144562236bSHarry Wentland void resource_validate_ctx_destruct(struct validate_context *context)
18154562236bSHarry Wentland {
18164562236bSHarry Wentland 	int i, j;
18174562236bSHarry Wentland 
1818ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1819ab2541b6SAric Cyr 		for (j = 0; j < context->stream_status[i].surface_count; j++)
18204562236bSHarry Wentland 			dc_surface_release(
1821ab2541b6SAric Cyr 				context->stream_status[i].surfaces[j]);
18224562236bSHarry Wentland 
1823ab2541b6SAric Cyr 		context->stream_status[i].surface_count = 0;
1824ab2541b6SAric Cyr 		dc_stream_release(&context->streams[i]->public);
1825ab2541b6SAric Cyr 		context->streams[i] = NULL;
18264562236bSHarry Wentland 	}
18274562236bSHarry Wentland }
18284562236bSHarry Wentland 
18294562236bSHarry Wentland /*
1830ab2541b6SAric Cyr  * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced
18314562236bSHarry Wentland  * by the src_ctx
18324562236bSHarry Wentland  */
18334562236bSHarry Wentland void resource_validate_ctx_copy_construct(
18344562236bSHarry Wentland 		const struct validate_context *src_ctx,
18354562236bSHarry Wentland 		struct validate_context *dst_ctx)
18364562236bSHarry Wentland {
18374562236bSHarry Wentland 	int i, j;
18384562236bSHarry Wentland 
18394562236bSHarry Wentland 	*dst_ctx = *src_ctx;
18404562236bSHarry Wentland 
18414562236bSHarry Wentland 	for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) {
18424562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
18434562236bSHarry Wentland 
18444562236bSHarry Wentland 		if (cur_pipe->top_pipe)
18454562236bSHarry Wentland 			cur_pipe->top_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
18464562236bSHarry Wentland 
18474562236bSHarry Wentland 		if (cur_pipe->bottom_pipe)
18484562236bSHarry Wentland 			cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
18494562236bSHarry Wentland 
18504562236bSHarry Wentland 	}
18514562236bSHarry Wentland 
1852ab2541b6SAric Cyr 	for (i = 0; i < dst_ctx->stream_count; i++) {
1853ab2541b6SAric Cyr 		dc_stream_retain(&dst_ctx->streams[i]->public);
1854ab2541b6SAric Cyr 		for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++)
18554562236bSHarry Wentland 			dc_surface_retain(
1856ab2541b6SAric Cyr 				dst_ctx->stream_status[i].surfaces[j]);
18574562236bSHarry Wentland 	}
18584562236bSHarry Wentland }
18594562236bSHarry Wentland 
18604562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll(
18614562236bSHarry Wentland 		struct resource_context *res_ctx)
18624562236bSHarry Wentland {
18634562236bSHarry Wentland 	int i;
18644562236bSHarry Wentland 
18654562236bSHarry Wentland 	for (i = 0; i < res_ctx->pool->clk_src_count; ++i) {
18664562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
18674562236bSHarry Wentland 			return res_ctx->pool->clock_sources[i];
18684562236bSHarry Wentland 	}
18694562236bSHarry Wentland 
18704562236bSHarry Wentland 	return NULL;
18714562236bSHarry Wentland }
18724562236bSHarry Wentland 
18734562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
18744562236bSHarry Wentland {
18754562236bSHarry Wentland 	enum signal_type signal = SIGNAL_TYPE_NONE;
18766e4d6beeSTony Cheng 	struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame;
18774562236bSHarry Wentland 
18784562236bSHarry Wentland 	/* default all packets to invalid */
18796e4d6beeSTony Cheng 	info->avi.valid = false;
18806e4d6beeSTony Cheng 	info->gamut.valid = false;
18816e4d6beeSTony Cheng 	info->vendor.valid = false;
18826e4d6beeSTony Cheng 	info->hdrsmd.valid = false;
18836e4d6beeSTony Cheng 	info->vsc.valid = false;
18844562236bSHarry Wentland 
18854562236bSHarry Wentland 	signal = pipe_ctx->stream->signal;
18864562236bSHarry Wentland 
18874562236bSHarry Wentland 	/* HDMi and DP have different info packets*/
18884562236bSHarry Wentland 	if (dc_is_hdmi_signal(signal)) {
18896e4d6beeSTony Cheng 		set_avi_info_frame(&info->avi, pipe_ctx);
18906e4d6beeSTony Cheng 
18916e4d6beeSTony Cheng 		set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
18926e4d6beeSTony Cheng 
18936e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
18946e4d6beeSTony Cheng 
18956e4d6beeSTony Cheng 		set_hdr_static_info_packet(&info->hdrsmd,
18966e4d6beeSTony Cheng 				pipe_ctx->surface, pipe_ctx->stream);
18976e4d6beeSTony Cheng 
1898a33fa99dSHarry Wentland 	} else if (dc_is_dp_signal(signal)) {
18996e4d6beeSTony Cheng 		set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
19006e4d6beeSTony Cheng 
19016e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
19026e4d6beeSTony Cheng 
19036e4d6beeSTony Cheng 		set_hdr_static_info_packet(&info->hdrsmd,
19046e4d6beeSTony Cheng 				pipe_ctx->surface, pipe_ctx->stream);
1905a33fa99dSHarry Wentland 	}
19064562236bSHarry Wentland 
19076e4d6beeSTony Cheng 	patch_gamut_packet_checksum(&info->gamut);
19084562236bSHarry Wentland }
19094562236bSHarry Wentland 
19104562236bSHarry Wentland enum dc_status resource_map_clock_resources(
19114562236bSHarry Wentland 		const struct core_dc *dc,
19124562236bSHarry Wentland 		struct validate_context *context)
19134562236bSHarry Wentland {
1914ab2541b6SAric Cyr 	int i, j;
19154562236bSHarry Wentland 
19164562236bSHarry Wentland 	/* acquire new resources */
1917ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
1918ab2541b6SAric Cyr 		const struct core_stream *stream = context->streams[i];
19194562236bSHarry Wentland 
19204562236bSHarry Wentland 		if (resource_is_stream_unchanged(dc->current_context, stream))
19214562236bSHarry Wentland 			continue;
19224562236bSHarry Wentland 
1923ab2541b6SAric Cyr 		for (j = 0; j < MAX_PIPES; j++) {
19244562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx =
1925ab2541b6SAric Cyr 				&context->res_ctx.pipe_ctx[j];
19264562236bSHarry Wentland 
1927ab2541b6SAric Cyr 			if (context->res_ctx.pipe_ctx[j].stream != stream)
19284562236bSHarry Wentland 				continue;
19294562236bSHarry Wentland 
19304562236bSHarry Wentland 			if (dc_is_dp_signal(pipe_ctx->stream->signal)
19314562236bSHarry Wentland 				|| pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
19324562236bSHarry Wentland 				pipe_ctx->clock_source =
19334562236bSHarry Wentland 					context->res_ctx.pool->dp_clock_source;
19344562236bSHarry Wentland 			else {
19354562236bSHarry Wentland 				pipe_ctx->clock_source = NULL;
19364562236bSHarry Wentland 
19374562236bSHarry Wentland 				if (!dc->public.config.disable_disp_pll_sharing)
19384562236bSHarry Wentland 					resource_find_used_clk_src_for_sharing(
19394562236bSHarry Wentland 						&context->res_ctx,
19404562236bSHarry Wentland 						pipe_ctx);
19414562236bSHarry Wentland 
19424562236bSHarry Wentland 				if (pipe_ctx->clock_source == NULL)
19434562236bSHarry Wentland 					pipe_ctx->clock_source =
19444562236bSHarry Wentland 						dc_resource_find_first_free_pll(&context->res_ctx);
19454562236bSHarry Wentland 			}
19464562236bSHarry Wentland 
19474562236bSHarry Wentland 			if (pipe_ctx->clock_source == NULL)
19484562236bSHarry Wentland 				return DC_NO_CLOCK_SOURCE_RESOURCE;
19494562236bSHarry Wentland 
19504562236bSHarry Wentland 			resource_reference_clock_source(
19514562236bSHarry Wentland 				&context->res_ctx,
19524562236bSHarry Wentland 				pipe_ctx->clock_source);
19534562236bSHarry Wentland 
19544562236bSHarry Wentland 			/* only one cs per stream regardless of mpo */
19554562236bSHarry Wentland 			break;
19564562236bSHarry Wentland 		}
19574562236bSHarry Wentland 	}
19584562236bSHarry Wentland 
19594562236bSHarry Wentland 	return DC_OK;
19604562236bSHarry Wentland }
19614562236bSHarry Wentland 
19624562236bSHarry Wentland /*
19634562236bSHarry Wentland  * Note: We need to disable output if clock sources change,
19644562236bSHarry Wentland  * since bios does optimization and doesn't apply if changing
19654562236bSHarry Wentland  * PHY when not already disabled.
19664562236bSHarry Wentland  */
19674562236bSHarry Wentland bool pipe_need_reprogram(
19684562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx_old,
19694562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
19704562236bSHarry Wentland {
19714562236bSHarry Wentland 	if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
19724562236bSHarry Wentland 		return true;
19734562236bSHarry Wentland 
19744562236bSHarry Wentland 	if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
19754562236bSHarry Wentland 		return true;
19764562236bSHarry Wentland 
19774562236bSHarry Wentland 	if (pipe_ctx_old->audio != pipe_ctx->audio)
19784562236bSHarry Wentland 		return true;
19794562236bSHarry Wentland 
19804562236bSHarry Wentland 	if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
19814562236bSHarry Wentland 			&& pipe_ctx_old->stream != pipe_ctx->stream)
19824562236bSHarry Wentland 		return true;
19834562236bSHarry Wentland 
19844562236bSHarry Wentland 	if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc)
19854562236bSHarry Wentland 		return true;
19864562236bSHarry Wentland 
19874562236bSHarry Wentland 	if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
19884562236bSHarry Wentland 		return true;
19894562236bSHarry Wentland 
19904562236bSHarry Wentland 
19914562236bSHarry Wentland 	return false;
19924562236bSHarry Wentland }
1993