14562236bSHarry Wentland /*
24562236bSHarry Wentland * Copyright 2012-15 Advanced Micro Devices, Inc.
34562236bSHarry Wentland  *
44562236bSHarry Wentland  * Permission is hereby granted, free of charge, to any person obtaining a
54562236bSHarry Wentland  * copy of this software and associated documentation files (the "Software"),
64562236bSHarry Wentland  * to deal in the Software without restriction, including without limitation
74562236bSHarry Wentland  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84562236bSHarry Wentland  * and/or sell copies of the Software, and to permit persons to whom the
94562236bSHarry Wentland  * Software is furnished to do so, subject to the following conditions:
104562236bSHarry Wentland  *
114562236bSHarry Wentland  * The above copyright notice and this permission notice shall be included in
124562236bSHarry Wentland  * all copies or substantial portions of the Software.
134562236bSHarry Wentland  *
144562236bSHarry Wentland  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154562236bSHarry Wentland  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
164562236bSHarry Wentland  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
174562236bSHarry Wentland  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
184562236bSHarry Wentland  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
194562236bSHarry Wentland  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
204562236bSHarry Wentland  * OTHER DEALINGS IN THE SOFTWARE.
214562236bSHarry Wentland  *
224562236bSHarry Wentland  * Authors: AMD
234562236bSHarry Wentland  *
244562236bSHarry Wentland  */
254562236bSHarry Wentland #include "dm_services.h"
264562236bSHarry Wentland 
274562236bSHarry Wentland #include "resource.h"
284562236bSHarry Wentland #include "include/irq_service_interface.h"
294562236bSHarry Wentland #include "link_encoder.h"
304562236bSHarry Wentland #include "stream_encoder.h"
314562236bSHarry Wentland #include "opp.h"
324562236bSHarry Wentland #include "timing_generator.h"
334562236bSHarry Wentland #include "transform.h"
345ac3d3c9SCharlene Liu #include "core_types.h"
354562236bSHarry Wentland #include "set_mode_types.h"
364562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h"
374562236bSHarry Wentland 
384562236bSHarry Wentland #include "dce80/dce80_resource.h"
394562236bSHarry Wentland #include "dce100/dce100_resource.h"
404562236bSHarry Wentland #include "dce110/dce110_resource.h"
414562236bSHarry Wentland #include "dce112/dce112_resource.h"
42ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
43ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h"
44ff5ef992SAlex Deucher #endif
452c8ad2d5SAlex Deucher #include "dce120/dce120_resource.h"
464562236bSHarry Wentland 
474562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
484562236bSHarry Wentland {
494562236bSHarry Wentland 	enum dce_version dc_version = DCE_VERSION_UNKNOWN;
504562236bSHarry Wentland 	switch (asic_id.chip_family) {
514562236bSHarry Wentland 
524562236bSHarry Wentland 	case FAMILY_CI:
534562236bSHarry Wentland 	case FAMILY_KV:
544562236bSHarry Wentland 		dc_version = DCE_VERSION_8_0;
554562236bSHarry Wentland 		break;
564562236bSHarry Wentland 	case FAMILY_CZ:
574562236bSHarry Wentland 		dc_version = DCE_VERSION_11_0;
584562236bSHarry Wentland 		break;
594562236bSHarry Wentland 
604562236bSHarry Wentland 	case FAMILY_VI:
614562236bSHarry Wentland 		if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
624562236bSHarry Wentland 				ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
634562236bSHarry Wentland 			dc_version = DCE_VERSION_10_0;
644562236bSHarry Wentland 			break;
654562236bSHarry Wentland 		}
664562236bSHarry Wentland 		if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
67b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
68b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
694562236bSHarry Wentland 			dc_version = DCE_VERSION_11_2;
704562236bSHarry Wentland 		}
714562236bSHarry Wentland 		break;
722c8ad2d5SAlex Deucher 	case FAMILY_AI:
732c8ad2d5SAlex Deucher 		dc_version = DCE_VERSION_12_0;
742c8ad2d5SAlex Deucher 		break;
75ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
76ff5ef992SAlex Deucher 	case FAMILY_RV:
77ff5ef992SAlex Deucher 		dc_version = DCN_VERSION_1_0;
78ff5ef992SAlex Deucher 		break;
79ff5ef992SAlex Deucher #endif
804562236bSHarry Wentland 	default:
814562236bSHarry Wentland 		dc_version = DCE_VERSION_UNKNOWN;
824562236bSHarry Wentland 		break;
834562236bSHarry Wentland 	}
844562236bSHarry Wentland 	return dc_version;
854562236bSHarry Wentland }
864562236bSHarry Wentland 
874562236bSHarry Wentland struct resource_pool *dc_create_resource_pool(
884562236bSHarry Wentland 				struct core_dc *dc,
894562236bSHarry Wentland 				int num_virtual_links,
904562236bSHarry Wentland 				enum dce_version dc_version,
914562236bSHarry Wentland 				struct hw_asic_id asic_id)
924562236bSHarry Wentland {
935ac3d3c9SCharlene Liu 	struct resource_pool *res_pool = NULL;
944562236bSHarry Wentland 
954562236bSHarry Wentland 	switch (dc_version) {
964562236bSHarry Wentland 	case DCE_VERSION_8_0:
975ac3d3c9SCharlene Liu 		res_pool = dce80_create_resource_pool(
984562236bSHarry Wentland 			num_virtual_links, dc);
995ac3d3c9SCharlene Liu 		break;
1004562236bSHarry Wentland 	case DCE_VERSION_10_0:
1015ac3d3c9SCharlene Liu 		res_pool = dce100_create_resource_pool(
1024562236bSHarry Wentland 				num_virtual_links, dc);
1035ac3d3c9SCharlene Liu 		break;
1044562236bSHarry Wentland 	case DCE_VERSION_11_0:
1055ac3d3c9SCharlene Liu 		res_pool = dce110_create_resource_pool(
1064562236bSHarry Wentland 			num_virtual_links, dc, asic_id);
1075ac3d3c9SCharlene Liu 		break;
1084562236bSHarry Wentland 	case DCE_VERSION_11_2:
1095ac3d3c9SCharlene Liu 		res_pool = dce112_create_resource_pool(
1104562236bSHarry Wentland 			num_virtual_links, dc);
1115ac3d3c9SCharlene Liu 		break;
1122c8ad2d5SAlex Deucher 	case DCE_VERSION_12_0:
1132c8ad2d5SAlex Deucher 		res_pool = dce120_create_resource_pool(
1142c8ad2d5SAlex Deucher 			num_virtual_links, dc);
1152c8ad2d5SAlex Deucher 		break;
116ff5ef992SAlex Deucher 
117ff5ef992SAlex Deucher #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
118ff5ef992SAlex Deucher 	case DCN_VERSION_1_0:
119ff5ef992SAlex Deucher 		res_pool = dcn10_create_resource_pool(
120ff5ef992SAlex Deucher 			num_virtual_links, dc);
121ff5ef992SAlex Deucher 		break;
122ff5ef992SAlex Deucher #endif
1233639fa68SZeyu Fan 
1243639fa68SZeyu Fan 
1254562236bSHarry Wentland 	default:
1264562236bSHarry Wentland 		break;
1274562236bSHarry Wentland 	}
1285ac3d3c9SCharlene Liu 	if (res_pool != NULL) {
1291515a47bSHarry Wentland 		struct dc_firmware_info fw_info = { { 0 } };
1304562236bSHarry Wentland 
1315ac3d3c9SCharlene Liu 		if (dc->ctx->dc_bios->funcs->get_firmware_info(
1325ac3d3c9SCharlene Liu 				dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) {
1335ac3d3c9SCharlene Liu 				res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency;
1345ac3d3c9SCharlene Liu 			} else
1355ac3d3c9SCharlene Liu 				ASSERT_CRITICAL(false);
1365ac3d3c9SCharlene Liu 	}
1375ac3d3c9SCharlene Liu 
1385ac3d3c9SCharlene Liu 	return res_pool;
1394562236bSHarry Wentland }
1404562236bSHarry Wentland 
1414562236bSHarry Wentland void dc_destroy_resource_pool(struct core_dc *dc)
1424562236bSHarry Wentland {
1434562236bSHarry Wentland 	if (dc) {
1444562236bSHarry Wentland 		if (dc->res_pool)
1454562236bSHarry Wentland 			dc->res_pool->funcs->destroy(&dc->res_pool);
1464562236bSHarry Wentland 
1474562236bSHarry Wentland 		if (dc->hwseq)
1484562236bSHarry Wentland 			dm_free(dc->hwseq);
1494562236bSHarry Wentland 	}
1504562236bSHarry Wentland }
1514562236bSHarry Wentland 
1524562236bSHarry Wentland static void update_num_audio(
1534562236bSHarry Wentland 	const struct resource_straps *straps,
1544562236bSHarry Wentland 	unsigned int *num_audio,
1554562236bSHarry Wentland 	struct audio_support *aud_support)
1564562236bSHarry Wentland {
1574562236bSHarry Wentland 	if (straps->hdmi_disable == 0) {
1584562236bSHarry Wentland 		aud_support->hdmi_audio_native = true;
1594562236bSHarry Wentland 		aud_support->hdmi_audio_on_dongle = true;
1604562236bSHarry Wentland 		aud_support->dp_audio = true;
1614562236bSHarry Wentland 	} else {
1624562236bSHarry Wentland 		if (straps->dc_pinstraps_audio & 0x2) {
1634562236bSHarry Wentland 			aud_support->hdmi_audio_on_dongle = true;
1644562236bSHarry Wentland 			aud_support->dp_audio = true;
1654562236bSHarry Wentland 		} else {
1664562236bSHarry Wentland 			aud_support->dp_audio = true;
1674562236bSHarry Wentland 		}
1684562236bSHarry Wentland 	}
1694562236bSHarry Wentland 
1704562236bSHarry Wentland 	switch (straps->audio_stream_number) {
1714562236bSHarry Wentland 	case 0: /* multi streams supported */
1724562236bSHarry Wentland 		break;
1734562236bSHarry Wentland 	case 1: /* multi streams not supported */
1744562236bSHarry Wentland 		*num_audio = 1;
1754562236bSHarry Wentland 		break;
1764562236bSHarry Wentland 	default:
1774562236bSHarry Wentland 		DC_ERR("DC: unexpected audio fuse!\n");
17817a96033SJulia Lawall 	}
1794562236bSHarry Wentland }
1804562236bSHarry Wentland 
1814562236bSHarry Wentland bool resource_construct(
1824562236bSHarry Wentland 	unsigned int num_virtual_links,
1834562236bSHarry Wentland 	struct core_dc *dc,
1844562236bSHarry Wentland 	struct resource_pool *pool,
1854562236bSHarry Wentland 	const struct resource_create_funcs *create_funcs)
1864562236bSHarry Wentland {
1874562236bSHarry Wentland 	struct dc_context *ctx = dc->ctx;
1884562236bSHarry Wentland 	const struct resource_caps *caps = pool->res_cap;
1894562236bSHarry Wentland 	int i;
1904562236bSHarry Wentland 	unsigned int num_audio = caps->num_audio;
1914562236bSHarry Wentland 	struct resource_straps straps = {0};
1924562236bSHarry Wentland 
1934562236bSHarry Wentland 	if (create_funcs->read_dce_straps)
1944562236bSHarry Wentland 		create_funcs->read_dce_straps(dc->ctx, &straps);
1954562236bSHarry Wentland 
1964562236bSHarry Wentland 	pool->audio_count = 0;
1974562236bSHarry Wentland 	if (create_funcs->create_audio) {
1984562236bSHarry Wentland 		/* find the total number of streams available via the
1994562236bSHarry Wentland 		 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
2004562236bSHarry Wentland 		 * registers (one for each pin) starting from pin 1
2014562236bSHarry Wentland 		 * up to the max number of audio pins.
2024562236bSHarry Wentland 		 * We stop on the first pin where
2034562236bSHarry Wentland 		 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
2044562236bSHarry Wentland 		 */
2054562236bSHarry Wentland 		update_num_audio(&straps, &num_audio, &pool->audio_support);
2064562236bSHarry Wentland 		for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
2074562236bSHarry Wentland 			struct audio *aud = create_funcs->create_audio(ctx, i);
2084562236bSHarry Wentland 
2094562236bSHarry Wentland 			if (aud == NULL) {
2104562236bSHarry Wentland 				DC_ERR("DC: failed to create audio!\n");
2114562236bSHarry Wentland 				return false;
2124562236bSHarry Wentland 			}
2134562236bSHarry Wentland 
2144562236bSHarry Wentland 			if (!aud->funcs->endpoint_valid(aud)) {
2154562236bSHarry Wentland 				aud->funcs->destroy(&aud);
2164562236bSHarry Wentland 				break;
2174562236bSHarry Wentland 			}
2184562236bSHarry Wentland 
2194562236bSHarry Wentland 			pool->audios[i] = aud;
2204562236bSHarry Wentland 			pool->audio_count++;
2214562236bSHarry Wentland 		}
2224562236bSHarry Wentland 	}
2234562236bSHarry Wentland 
2244562236bSHarry Wentland 	pool->stream_enc_count = 0;
2254562236bSHarry Wentland 	if (create_funcs->create_stream_encoder) {
2264562236bSHarry Wentland 		for (i = 0; i < caps->num_stream_encoder; i++) {
2274562236bSHarry Wentland 			pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
2284562236bSHarry Wentland 			if (pool->stream_enc[i] == NULL)
2294562236bSHarry Wentland 				DC_ERR("DC: failed to create stream_encoder!\n");
2304562236bSHarry Wentland 			pool->stream_enc_count++;
2314562236bSHarry Wentland 		}
2324562236bSHarry Wentland 	}
2334562236bSHarry Wentland 
2344562236bSHarry Wentland 	for (i = 0; i < num_virtual_links; i++) {
2354562236bSHarry Wentland 		pool->stream_enc[pool->stream_enc_count] =
2364562236bSHarry Wentland 			virtual_stream_encoder_create(
2374562236bSHarry Wentland 					ctx, ctx->dc_bios);
2384562236bSHarry Wentland 		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
2394562236bSHarry Wentland 			DC_ERR("DC: failed to create stream_encoder!\n");
2404562236bSHarry Wentland 			return false;
2414562236bSHarry Wentland 		}
2424562236bSHarry Wentland 		pool->stream_enc_count++;
2434562236bSHarry Wentland 	}
2444562236bSHarry Wentland 
2454562236bSHarry Wentland 	dc->hwseq = create_funcs->create_hwseq(ctx);
2464562236bSHarry Wentland 
2474562236bSHarry Wentland 	return true;
2484562236bSHarry Wentland }
2494562236bSHarry Wentland 
2504562236bSHarry Wentland 
2514562236bSHarry Wentland void resource_unreference_clock_source(
2524562236bSHarry Wentland 		struct resource_context *res_ctx,
253a2b8659dSTony Cheng 		const struct resource_pool *pool,
2548c737fccSYongqiang Sun 		struct clock_source **clock_source)
2554562236bSHarry Wentland {
2564562236bSHarry Wentland 	int i;
257a2b8659dSTony Cheng 	for (i = 0; i < pool->clk_src_count; i++) {
258a2b8659dSTony Cheng 		if (pool->clock_sources[i] != *clock_source)
2594562236bSHarry Wentland 			continue;
2604562236bSHarry Wentland 
2614562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]--;
2624562236bSHarry Wentland 
2634562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
2648c737fccSYongqiang Sun 			(*clock_source)->funcs->cs_power_down(*clock_source);
2654562236bSHarry Wentland 
2664562236bSHarry Wentland 		break;
2674562236bSHarry Wentland 	}
2684562236bSHarry Wentland 
269a2b8659dSTony Cheng 	if (pool->dp_clock_source == *clock_source) {
2704562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count--;
2714562236bSHarry Wentland 
2724562236bSHarry Wentland 		if (res_ctx->dp_clock_source_ref_count == 0)
2738c737fccSYongqiang Sun 			(*clock_source)->funcs->cs_power_down(*clock_source);
2744562236bSHarry Wentland 	}
2758c737fccSYongqiang Sun 	*clock_source = NULL;
2764562236bSHarry Wentland }
2774562236bSHarry Wentland 
2784562236bSHarry Wentland void resource_reference_clock_source(
2794562236bSHarry Wentland 		struct resource_context *res_ctx,
280a2b8659dSTony Cheng 		const struct resource_pool *pool,
2814562236bSHarry Wentland 		struct clock_source *clock_source)
2824562236bSHarry Wentland {
2834562236bSHarry Wentland 	int i;
284a2b8659dSTony Cheng 	for (i = 0; i < pool->clk_src_count; i++) {
285a2b8659dSTony Cheng 		if (pool->clock_sources[i] != clock_source)
2864562236bSHarry Wentland 			continue;
2874562236bSHarry Wentland 
2884562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]++;
2894562236bSHarry Wentland 		break;
2904562236bSHarry Wentland 	}
2914562236bSHarry Wentland 
292a2b8659dSTony Cheng 	if (pool->dp_clock_source == clock_source)
2934562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count++;
2944562236bSHarry Wentland }
2954562236bSHarry Wentland 
2964562236bSHarry Wentland bool resource_are_streams_timing_synchronizable(
2970971c40eSHarry Wentland 	struct dc_stream_state *stream1,
2980971c40eSHarry Wentland 	struct dc_stream_state *stream2)
2994562236bSHarry Wentland {
3004fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.h_total != stream2->timing.h_total)
3014562236bSHarry Wentland 		return false;
3024562236bSHarry Wentland 
3034fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.v_total != stream2->timing.v_total)
3044562236bSHarry Wentland 		return false;
3054562236bSHarry Wentland 
3064fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.h_addressable
3074fa086b9SLeo (Sunpeng) Li 				!= stream2->timing.h_addressable)
3084562236bSHarry Wentland 		return false;
3094562236bSHarry Wentland 
3104fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.v_addressable
3114fa086b9SLeo (Sunpeng) Li 				!= stream2->timing.v_addressable)
3124562236bSHarry Wentland 		return false;
3134562236bSHarry Wentland 
3144fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.pix_clk_khz
3154fa086b9SLeo (Sunpeng) Li 				!= stream2->timing.pix_clk_khz)
3164562236bSHarry Wentland 		return false;
3174562236bSHarry Wentland 
3184562236bSHarry Wentland 	if (stream1->phy_pix_clk != stream2->phy_pix_clk
3197e2fe319SCharlene Liu 			&& (!dc_is_dp_signal(stream1->signal)
3207e2fe319SCharlene Liu 			|| !dc_is_dp_signal(stream2->signal)))
3214562236bSHarry Wentland 		return false;
3224562236bSHarry Wentland 
3234562236bSHarry Wentland 	return true;
3244562236bSHarry Wentland }
3254562236bSHarry Wentland 
3264562236bSHarry Wentland static bool is_sharable_clk_src(
3274562236bSHarry Wentland 	const struct pipe_ctx *pipe_with_clk_src,
3284562236bSHarry Wentland 	const struct pipe_ctx *pipe)
3294562236bSHarry Wentland {
3304562236bSHarry Wentland 	if (pipe_with_clk_src->clock_source == NULL)
3314562236bSHarry Wentland 		return false;
3324562236bSHarry Wentland 
3334562236bSHarry Wentland 	if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
3344562236bSHarry Wentland 		return false;
3354562236bSHarry Wentland 
3364562236bSHarry Wentland 	if (dc_is_dp_signal(pipe_with_clk_src->stream->signal))
3374562236bSHarry Wentland 		return false;
3384562236bSHarry Wentland 
3394562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
3404562236bSHarry Wentland 			&& dc_is_dvi_signal(pipe->stream->signal))
3414562236bSHarry Wentland 		return false;
3424562236bSHarry Wentland 
3434562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe->stream->signal)
3444562236bSHarry Wentland 			&& dc_is_dvi_signal(pipe_with_clk_src->stream->signal))
3454562236bSHarry Wentland 		return false;
3464562236bSHarry Wentland 
3474562236bSHarry Wentland 	if (!resource_are_streams_timing_synchronizable(
3484562236bSHarry Wentland 			pipe_with_clk_src->stream, pipe->stream))
3494562236bSHarry Wentland 		return false;
3504562236bSHarry Wentland 
3514562236bSHarry Wentland 	return true;
3524562236bSHarry Wentland }
3534562236bSHarry Wentland 
3544562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing(
3554562236bSHarry Wentland 					struct resource_context *res_ctx,
3564562236bSHarry Wentland 					struct pipe_ctx *pipe_ctx)
3574562236bSHarry Wentland {
3584562236bSHarry Wentland 	int i;
3594562236bSHarry Wentland 
3604562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
3614562236bSHarry Wentland 		if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
3624562236bSHarry Wentland 			return res_ctx->pipe_ctx[i].clock_source;
3634562236bSHarry Wentland 	}
3644562236bSHarry Wentland 
3654562236bSHarry Wentland 	return NULL;
3664562236bSHarry Wentland }
3674562236bSHarry Wentland 
3684562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface(
3694562236bSHarry Wentland 		enum surface_pixel_format surface_pixel_format)
3704562236bSHarry Wentland {
3714562236bSHarry Wentland 	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
3724562236bSHarry Wentland 
3734562236bSHarry Wentland 	switch (surface_pixel_format) {
3744562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
3754562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_INDEX8;
3764562236bSHarry Wentland 		break;
3774562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
3784562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
3794562236bSHarry Wentland 		break;
3804562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
3814562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
3824562236bSHarry Wentland 		break;
3834562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
3844562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
3854562236bSHarry Wentland 		break;
3868693049aSTony Cheng 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
3874562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
3884562236bSHarry Wentland 		break;
3894562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
3904562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
3914562236bSHarry Wentland 		break;
3924562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
3934562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
3944562236bSHarry Wentland 		break;
3954562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
3964562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
3974562236bSHarry Wentland 		break;
3984562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
3994562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
4004562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_FP16;
4014562236bSHarry Wentland 		break;
4024562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
4034562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
40487449a90SAnthony Koo 		dal_pixel_format = PIXEL_FORMAT_420BPP8;
4054562236bSHarry Wentland 		break;
406ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
407ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
40887449a90SAnthony Koo 		dal_pixel_format = PIXEL_FORMAT_420BPP10;
409ffbcd19aSVitaly Prosyak 		break;
4104562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
4114562236bSHarry Wentland 	default:
4124562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
4134562236bSHarry Wentland 		break;
4144562236bSHarry Wentland 	}
4154562236bSHarry Wentland 	return dal_pixel_format;
4164562236bSHarry Wentland }
4174562236bSHarry Wentland 
4184562236bSHarry Wentland static void rect_swap_helper(struct rect *rect)
4194562236bSHarry Wentland {
4204562236bSHarry Wentland 	uint32_t temp = 0;
4214562236bSHarry Wentland 
4224562236bSHarry Wentland 	temp = rect->height;
4234562236bSHarry Wentland 	rect->height = rect->width;
4244562236bSHarry Wentland 	rect->width = temp;
4254562236bSHarry Wentland 
4264562236bSHarry Wentland 	temp = rect->x;
4274562236bSHarry Wentland 	rect->x = rect->y;
4284562236bSHarry Wentland 	rect->y = temp;
4294562236bSHarry Wentland }
4304562236bSHarry Wentland 
431b2d0a103SDmytro Laktyushkin static void calculate_viewport(struct pipe_ctx *pipe_ctx)
4324562236bSHarry Wentland {
4333be5262eSHarry Wentland 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
4340971c40eSHarry Wentland 	const struct dc_stream_state *stream = pipe_ctx->stream;
4356702a9acSHarry Wentland 	struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
4363be5262eSHarry Wentland 	struct rect surf_src = plane_state->src_rect;
4374562236bSHarry Wentland 	struct rect clip = { 0 };
43887449a90SAnthony Koo 	int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
43987449a90SAnthony Koo 			|| data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
4401fbd2cfcSDmytro Laktyushkin 	bool pri_split = pipe_ctx->bottom_pipe &&
4413be5262eSHarry Wentland 			pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state;
4421fbd2cfcSDmytro Laktyushkin 	bool sec_split = pipe_ctx->top_pipe &&
4433be5262eSHarry Wentland 			pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
4444562236bSHarry Wentland 
4457f5c22d1SVitaly Prosyak 	if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE ||
4467f5c22d1SVitaly Prosyak 		stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
4477b779c99SVitaly Prosyak 		pri_split = false;
4487b779c99SVitaly Prosyak 		sec_split = false;
4497b779c99SVitaly Prosyak 	}
45086006a7fSDmytro Laktyushkin 
4513be5262eSHarry Wentland 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
4523be5262eSHarry Wentland 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
45386006a7fSDmytro Laktyushkin 		rect_swap_helper(&surf_src);
45486006a7fSDmytro Laktyushkin 
4554562236bSHarry Wentland 	/* The actual clip is an intersection between stream
4564562236bSHarry Wentland 	 * source and surface clip
4574562236bSHarry Wentland 	 */
4583be5262eSHarry Wentland 	clip.x = stream->src.x > plane_state->clip_rect.x ?
4593be5262eSHarry Wentland 			stream->src.x : plane_state->clip_rect.x;
4604562236bSHarry Wentland 
4611fbd2cfcSDmytro Laktyushkin 	clip.width = stream->src.x + stream->src.width <
4623be5262eSHarry Wentland 			plane_state->clip_rect.x + plane_state->clip_rect.width ?
4631fbd2cfcSDmytro Laktyushkin 			stream->src.x + stream->src.width - clip.x :
4643be5262eSHarry Wentland 			plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ;
4654562236bSHarry Wentland 
4663be5262eSHarry Wentland 	clip.y = stream->src.y > plane_state->clip_rect.y ?
4673be5262eSHarry Wentland 			stream->src.y : plane_state->clip_rect.y;
4684562236bSHarry Wentland 
4691fbd2cfcSDmytro Laktyushkin 	clip.height = stream->src.y + stream->src.height <
4703be5262eSHarry Wentland 			plane_state->clip_rect.y + plane_state->clip_rect.height ?
4711fbd2cfcSDmytro Laktyushkin 			stream->src.y + stream->src.height - clip.y :
4723be5262eSHarry Wentland 			plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ;
4734562236bSHarry Wentland 
47486006a7fSDmytro Laktyushkin 	/* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio
4754562236bSHarry Wentland 	 * num_pixels = clip.num_pix * scl_ratio
4764562236bSHarry Wentland 	 */
4773be5262eSHarry Wentland 	data->viewport.x = surf_src.x + (clip.x - plane_state->dst_rect.x) *
4783be5262eSHarry Wentland 			surf_src.width / plane_state->dst_rect.width;
479b2d0a103SDmytro Laktyushkin 	data->viewport.width = clip.width *
4803be5262eSHarry Wentland 			surf_src.width / plane_state->dst_rect.width;
4814562236bSHarry Wentland 
4823be5262eSHarry Wentland 	data->viewport.y = surf_src.y + (clip.y - plane_state->dst_rect.y) *
4833be5262eSHarry Wentland 			surf_src.height / plane_state->dst_rect.height;
484b2d0a103SDmytro Laktyushkin 	data->viewport.height = clip.height *
4853be5262eSHarry Wentland 			surf_src.height / plane_state->dst_rect.height;
4864562236bSHarry Wentland 
487b2d0a103SDmytro Laktyushkin 	/* Round down, compensate in init */
488b2d0a103SDmytro Laktyushkin 	data->viewport_c.x = data->viewport.x / vpc_div;
489b2d0a103SDmytro Laktyushkin 	data->viewport_c.y = data->viewport.y / vpc_div;
490b2d0a103SDmytro Laktyushkin 	data->inits.h_c = (data->viewport.x % vpc_div) != 0 ?
491b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_half : dal_fixed31_32_zero;
492b2d0a103SDmytro Laktyushkin 	data->inits.v_c = (data->viewport.y % vpc_div) != 0 ?
493b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_half : dal_fixed31_32_zero;
494b2d0a103SDmytro Laktyushkin 	/* Round up, assume original video size always even dimensions */
495b2d0a103SDmytro Laktyushkin 	data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div;
496b2d0a103SDmytro Laktyushkin 	data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div;
497b2d0a103SDmytro Laktyushkin 
498b2d0a103SDmytro Laktyushkin 	/* Handle hsplit */
4991fbd2cfcSDmytro Laktyushkin 	if (pri_split || sec_split) {
5001fbd2cfcSDmytro Laktyushkin 		/* HMirror XOR Secondary_pipe XOR Rotation_180 */
5013be5262eSHarry Wentland 		bool right_view = (sec_split != plane_state->horizontal_mirror) !=
5023be5262eSHarry Wentland 					(plane_state->rotation == ROTATION_ANGLE_180);
5039e6c74ceSDmytro Laktyushkin 
5043be5262eSHarry Wentland 		if (plane_state->rotation == ROTATION_ANGLE_90
5053be5262eSHarry Wentland 				|| plane_state->rotation == ROTATION_ANGLE_270)
5061fbd2cfcSDmytro Laktyushkin 			/* Secondary_pipe XOR Rotation_270 */
5073be5262eSHarry Wentland 			right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split;
5089e6c74ceSDmytro Laktyushkin 
5099e6c74ceSDmytro Laktyushkin 		if (right_view) {
510b2d0a103SDmytro Laktyushkin 			data->viewport.width /= 2;
511b2d0a103SDmytro Laktyushkin 			data->viewport_c.width /= 2;
512b2d0a103SDmytro Laktyushkin 			data->viewport.x +=  data->viewport.width;
513b2d0a103SDmytro Laktyushkin 			data->viewport_c.x +=  data->viewport_c.width;
5149e6c74ceSDmytro Laktyushkin 			/* Ceil offset pipe */
515b2d0a103SDmytro Laktyushkin 			data->viewport.width += data->viewport.width % 2;
516b2d0a103SDmytro Laktyushkin 			data->viewport_c.width += data->viewport_c.width % 2;
5179e6c74ceSDmytro Laktyushkin 		} else {
518b2d0a103SDmytro Laktyushkin 			data->viewport.width /= 2;
519b2d0a103SDmytro Laktyushkin 			data->viewport_c.width /= 2;
520b2d0a103SDmytro Laktyushkin 		}
5214562236bSHarry Wentland 	}
5221fbd2cfcSDmytro Laktyushkin 
5233be5262eSHarry Wentland 	if (plane_state->rotation == ROTATION_ANGLE_90 ||
5243be5262eSHarry Wentland 			plane_state->rotation == ROTATION_ANGLE_270) {
5251fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport_c);
5261fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport);
5271fbd2cfcSDmytro Laktyushkin 	}
5289e6c74ceSDmytro Laktyushkin }
5294562236bSHarry Wentland 
530b2d0a103SDmytro Laktyushkin static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip)
5314562236bSHarry Wentland {
5323be5262eSHarry Wentland 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
5330971c40eSHarry Wentland 	const struct dc_stream_state *stream = pipe_ctx->stream;
5343be5262eSHarry Wentland 	struct rect surf_src = plane_state->src_rect;
5353be5262eSHarry Wentland 	struct rect surf_clip = plane_state->clip_rect;
536c802570eSDmytro Laktyushkin 	int recout_full_x, recout_full_y;
5374562236bSHarry Wentland 
5383be5262eSHarry Wentland 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
5393be5262eSHarry Wentland 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
54086006a7fSDmytro Laktyushkin 		rect_swap_helper(&surf_src);
54186006a7fSDmytro Laktyushkin 
5426702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x;
5434fa086b9SLeo (Sunpeng) Li 	if (stream->src.x < surf_clip.x)
5446702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x
5454fa086b9SLeo (Sunpeng) Li 			- stream->src.x) * stream->dst.width
5464fa086b9SLeo (Sunpeng) Li 						/ stream->src.width;
5474562236bSHarry Wentland 
5486702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width *
5494fa086b9SLeo (Sunpeng) Li 			stream->dst.width / stream->src.width;
5506702a9acSHarry Wentland 	if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x >
5514fa086b9SLeo (Sunpeng) Li 			stream->dst.x + stream->dst.width)
5526702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.recout.width =
5534fa086b9SLeo (Sunpeng) Li 			stream->dst.x + stream->dst.width
5546702a9acSHarry Wentland 						- pipe_ctx->plane_res.scl_data.recout.x;
5554562236bSHarry Wentland 
5566702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y;
5574fa086b9SLeo (Sunpeng) Li 	if (stream->src.y < surf_clip.y)
5586702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y
5594fa086b9SLeo (Sunpeng) Li 			- stream->src.y) * stream->dst.height
5604fa086b9SLeo (Sunpeng) Li 						/ stream->src.height;
5614562236bSHarry Wentland 
5626702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height *
5634fa086b9SLeo (Sunpeng) Li 			stream->dst.height / stream->src.height;
5646702a9acSHarry Wentland 	if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y >
5654fa086b9SLeo (Sunpeng) Li 			stream->dst.y + stream->dst.height)
5666702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.recout.height =
5674fa086b9SLeo (Sunpeng) Li 			stream->dst.y + stream->dst.height
5686702a9acSHarry Wentland 						- pipe_ctx->plane_res.scl_data.recout.y;
569b2d0a103SDmytro Laktyushkin 
5707b779c99SVitaly Prosyak 	/* Handle h & vsplit */
5713be5262eSHarry Wentland 	if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state ==
5723be5262eSHarry Wentland 		pipe_ctx->plane_state) {
5734fa086b9SLeo (Sunpeng) Li 		if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
5746702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.recout.height /= 2;
5756702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height;
5767b779c99SVitaly Prosyak 			/* Floor primary pipe, ceil 2ndary pipe */
5776702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.recout.height += pipe_ctx->plane_res.scl_data.recout.height % 2;
5787b779c99SVitaly Prosyak 		} else {
5796702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.recout.width /= 2;
5806702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width;
5816702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.recout.width += pipe_ctx->plane_res.scl_data.recout.width % 2;
5827b779c99SVitaly Prosyak 		}
5837b779c99SVitaly Prosyak 	} else if (pipe_ctx->bottom_pipe &&
5843be5262eSHarry Wentland 			pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) {
5854fa086b9SLeo (Sunpeng) Li 		if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
5866702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.recout.height /= 2;
5877b779c99SVitaly Prosyak 		else
5886702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.recout.width /= 2;
5894562236bSHarry Wentland 	}
5904562236bSHarry Wentland 
59186006a7fSDmytro Laktyushkin 	/* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset)
59286006a7fSDmytro Laktyushkin 	 * 				* 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl
593c802570eSDmytro Laktyushkin 	 * 				ratio)
594c802570eSDmytro Laktyushkin 	 */
5953be5262eSHarry Wentland 	recout_full_x = stream->dst.x + (plane_state->dst_rect.x -  stream->src.x)
5964fa086b9SLeo (Sunpeng) Li 					* stream->dst.width / stream->src.width -
5973be5262eSHarry Wentland 			surf_src.x * plane_state->dst_rect.width / surf_src.width
5984fa086b9SLeo (Sunpeng) Li 					* stream->dst.width / stream->src.width;
5993be5262eSHarry Wentland 	recout_full_y = stream->dst.y + (plane_state->dst_rect.y -  stream->src.y)
6004fa086b9SLeo (Sunpeng) Li 					* stream->dst.height / stream->src.height -
6013be5262eSHarry Wentland 			surf_src.y * plane_state->dst_rect.height / surf_src.height
6024fa086b9SLeo (Sunpeng) Li 					* stream->dst.height / stream->src.height;
603c802570eSDmytro Laktyushkin 
6046702a9acSHarry Wentland 	recout_skip->width = pipe_ctx->plane_res.scl_data.recout.x - recout_full_x;
6056702a9acSHarry Wentland 	recout_skip->height = pipe_ctx->plane_res.scl_data.recout.y - recout_full_y;
606b2d0a103SDmytro Laktyushkin }
607b2d0a103SDmytro Laktyushkin 
608b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
6094562236bSHarry Wentland {
6103be5262eSHarry Wentland 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
6110971c40eSHarry Wentland 	const struct dc_stream_state *stream = pipe_ctx->stream;
6123be5262eSHarry Wentland 	struct rect surf_src = plane_state->src_rect;
6134fa086b9SLeo (Sunpeng) Li 	const int in_w = stream->src.width;
6144fa086b9SLeo (Sunpeng) Li 	const int in_h = stream->src.height;
6154fa086b9SLeo (Sunpeng) Li 	const int out_w = stream->dst.width;
6164fa086b9SLeo (Sunpeng) Li 	const int out_h = stream->dst.height;
6174562236bSHarry Wentland 
6183be5262eSHarry Wentland 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
6193be5262eSHarry Wentland 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
62086006a7fSDmytro Laktyushkin 		rect_swap_helper(&surf_src);
62186006a7fSDmytro Laktyushkin 
6226702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.horz = dal_fixed31_32_from_fraction(
62386006a7fSDmytro Laktyushkin 					surf_src.width,
6243be5262eSHarry Wentland 					plane_state->dst_rect.width);
6256702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.vert = dal_fixed31_32_from_fraction(
62686006a7fSDmytro Laktyushkin 					surf_src.height,
6273be5262eSHarry Wentland 					plane_state->dst_rect.height);
6284562236bSHarry Wentland 
6294fa086b9SLeo (Sunpeng) Li 	if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
6306702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2;
6314fa086b9SLeo (Sunpeng) Li 	else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
6326702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2;
6334562236bSHarry Wentland 
6346702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64(
6356702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h);
6366702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64(
6376702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w);
6384562236bSHarry Wentland 
6396702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz;
6406702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert;
6414562236bSHarry Wentland 
6426702a9acSHarry Wentland 	if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8
6436702a9acSHarry Wentland 			|| pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) {
6446702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2;
6456702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2;
6464562236bSHarry Wentland 	}
6474562236bSHarry Wentland }
6484562236bSHarry Wentland 
649b2d0a103SDmytro Laktyushkin static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip)
6504562236bSHarry Wentland {
6516702a9acSHarry Wentland 	struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
6523be5262eSHarry Wentland 	struct rect src = pipe_ctx->plane_state->src_rect;
65387449a90SAnthony Koo 	int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
65487449a90SAnthony Koo 			|| data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
655b2d0a103SDmytro Laktyushkin 
65686006a7fSDmytro Laktyushkin 
6573be5262eSHarry Wentland 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
6583be5262eSHarry Wentland 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
65986006a7fSDmytro Laktyushkin 		rect_swap_helper(&src);
6601fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport_c);
6611fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport);
6621fbd2cfcSDmytro Laktyushkin 	}
6631fbd2cfcSDmytro Laktyushkin 
664b2d0a103SDmytro Laktyushkin 	/*
665b2d0a103SDmytro Laktyushkin 	 * Init calculated according to formula:
666b2d0a103SDmytro Laktyushkin 	 * 	init = (scaling_ratio + number_of_taps + 1) / 2
667b2d0a103SDmytro Laktyushkin 	 * 	init_bot = init + scaling_ratio
668b2d0a103SDmytro Laktyushkin 	 * 	init_c = init + truncated_vp_c_offset(from calculate viewport)
669b2d0a103SDmytro Laktyushkin 	 */
670b2d0a103SDmytro Laktyushkin 	data->inits.h = dal_fixed31_32_div_int(
671b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2);
672b2d0a103SDmytro Laktyushkin 
673b2d0a103SDmytro Laktyushkin 	data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int(
674b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2));
675b2d0a103SDmytro Laktyushkin 
676b2d0a103SDmytro Laktyushkin 	data->inits.v = dal_fixed31_32_div_int(
677b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2);
678b2d0a103SDmytro Laktyushkin 
679b2d0a103SDmytro Laktyushkin 	data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int(
680b2d0a103SDmytro Laktyushkin 			dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2));
681b2d0a103SDmytro Laktyushkin 
682b2d0a103SDmytro Laktyushkin 
683b2d0a103SDmytro Laktyushkin 	/* Adjust for viewport end clip-off */
684b2d0a103SDmytro Laktyushkin 	if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) {
685b2d0a103SDmytro Laktyushkin 		int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x;
6861fbd2cfcSDmytro Laktyushkin 		int int_part = dal_fixed31_32_floor(
6871fbd2cfcSDmytro Laktyushkin 				dal_fixed31_32_sub(data->inits.h, data->ratios.horz));
688b2d0a103SDmytro Laktyushkin 
6891fbd2cfcSDmytro Laktyushkin 		int_part = int_part > 0 ? int_part : 0;
690b2d0a103SDmytro Laktyushkin 		data->viewport.width += int_part < vp_clip ? int_part : vp_clip;
691b2d0a103SDmytro Laktyushkin 	}
692b2d0a103SDmytro Laktyushkin 	if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) {
693b2d0a103SDmytro Laktyushkin 		int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y;
6941fbd2cfcSDmytro Laktyushkin 		int int_part = dal_fixed31_32_floor(
6951fbd2cfcSDmytro Laktyushkin 				dal_fixed31_32_sub(data->inits.v, data->ratios.vert));
696b2d0a103SDmytro Laktyushkin 
6971fbd2cfcSDmytro Laktyushkin 		int_part = int_part > 0 ? int_part : 0;
698b2d0a103SDmytro Laktyushkin 		data->viewport.height += int_part < vp_clip ? int_part : vp_clip;
699b2d0a103SDmytro Laktyushkin 	}
700b2d0a103SDmytro Laktyushkin 	if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) {
701b2d0a103SDmytro Laktyushkin 		int vp_clip = (src.x + src.width) / vpc_div -
702b2d0a103SDmytro Laktyushkin 				data->viewport_c.width - data->viewport_c.x;
7031fbd2cfcSDmytro Laktyushkin 		int int_part = dal_fixed31_32_floor(
7041fbd2cfcSDmytro Laktyushkin 				dal_fixed31_32_sub(data->inits.h_c, data->ratios.horz_c));
705b2d0a103SDmytro Laktyushkin 
7061fbd2cfcSDmytro Laktyushkin 		int_part = int_part > 0 ? int_part : 0;
707b2d0a103SDmytro Laktyushkin 		data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip;
708b2d0a103SDmytro Laktyushkin 	}
709b2d0a103SDmytro Laktyushkin 	if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) {
710b2d0a103SDmytro Laktyushkin 		int vp_clip = (src.y + src.height) / vpc_div -
711b2d0a103SDmytro Laktyushkin 				data->viewport_c.height - data->viewport_c.y;
7121fbd2cfcSDmytro Laktyushkin 		int int_part = dal_fixed31_32_floor(
7131fbd2cfcSDmytro Laktyushkin 				dal_fixed31_32_sub(data->inits.v_c, data->ratios.vert_c));
714b2d0a103SDmytro Laktyushkin 
7151fbd2cfcSDmytro Laktyushkin 		int_part = int_part > 0 ? int_part : 0;
716b2d0a103SDmytro Laktyushkin 		data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip;
717b2d0a103SDmytro Laktyushkin 	}
718b2d0a103SDmytro Laktyushkin 
719b2d0a103SDmytro Laktyushkin 	/* Adjust for non-0 viewport offset */
720b2d0a103SDmytro Laktyushkin 	if (data->viewport.x) {
721b2d0a103SDmytro Laktyushkin 		int int_part;
722b2d0a103SDmytro Laktyushkin 
723b2d0a103SDmytro Laktyushkin 		data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int(
724b2d0a103SDmytro Laktyushkin 				data->ratios.horz, recout_skip->width));
725b2d0a103SDmytro Laktyushkin 		int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x;
726b2d0a103SDmytro Laktyushkin 		if (int_part < data->taps.h_taps) {
727b2d0a103SDmytro Laktyushkin 			int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ?
728b2d0a103SDmytro Laktyushkin 						(data->taps.h_taps - int_part) : data->viewport.x;
729b2d0a103SDmytro Laktyushkin 			data->viewport.x -= int_adj;
730b2d0a103SDmytro Laktyushkin 			data->viewport.width += int_adj;
731b2d0a103SDmytro Laktyushkin 			int_part += int_adj;
732b2d0a103SDmytro Laktyushkin 		} else if (int_part > data->taps.h_taps) {
733b2d0a103SDmytro Laktyushkin 			data->viewport.x += int_part - data->taps.h_taps;
734b2d0a103SDmytro Laktyushkin 			data->viewport.width -= int_part - data->taps.h_taps;
735b2d0a103SDmytro Laktyushkin 			int_part = data->taps.h_taps;
736b2d0a103SDmytro Laktyushkin 		}
737b2d0a103SDmytro Laktyushkin 		data->inits.h.value &= 0xffffffff;
738b2d0a103SDmytro Laktyushkin 		data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part);
739b2d0a103SDmytro Laktyushkin 	}
740b2d0a103SDmytro Laktyushkin 
741b2d0a103SDmytro Laktyushkin 	if (data->viewport_c.x) {
742b2d0a103SDmytro Laktyushkin 		int int_part;
743b2d0a103SDmytro Laktyushkin 
744b2d0a103SDmytro Laktyushkin 		data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int(
745b2d0a103SDmytro Laktyushkin 				data->ratios.horz_c, recout_skip->width));
746b2d0a103SDmytro Laktyushkin 		int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x;
747b2d0a103SDmytro Laktyushkin 		if (int_part < data->taps.h_taps_c) {
748b2d0a103SDmytro Laktyushkin 			int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ?
749b2d0a103SDmytro Laktyushkin 					(data->taps.h_taps_c - int_part) : data->viewport_c.x;
750b2d0a103SDmytro Laktyushkin 			data->viewport_c.x -= int_adj;
751b2d0a103SDmytro Laktyushkin 			data->viewport_c.width += int_adj;
752b2d0a103SDmytro Laktyushkin 			int_part += int_adj;
753b2d0a103SDmytro Laktyushkin 		} else if (int_part > data->taps.h_taps_c) {
754b2d0a103SDmytro Laktyushkin 			data->viewport_c.x += int_part - data->taps.h_taps_c;
755b2d0a103SDmytro Laktyushkin 			data->viewport_c.width -= int_part - data->taps.h_taps_c;
756b2d0a103SDmytro Laktyushkin 			int_part = data->taps.h_taps_c;
757b2d0a103SDmytro Laktyushkin 		}
758b2d0a103SDmytro Laktyushkin 		data->inits.h_c.value &= 0xffffffff;
759b2d0a103SDmytro Laktyushkin 		data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part);
760b2d0a103SDmytro Laktyushkin 	}
761b2d0a103SDmytro Laktyushkin 
762b2d0a103SDmytro Laktyushkin 	if (data->viewport.y) {
763b2d0a103SDmytro Laktyushkin 		int int_part;
764b2d0a103SDmytro Laktyushkin 
765b2d0a103SDmytro Laktyushkin 		data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int(
766b2d0a103SDmytro Laktyushkin 				data->ratios.vert, recout_skip->height));
767b2d0a103SDmytro Laktyushkin 		int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y;
768b2d0a103SDmytro Laktyushkin 		if (int_part < data->taps.v_taps) {
769b2d0a103SDmytro Laktyushkin 			int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ?
770b2d0a103SDmytro Laktyushkin 						(data->taps.v_taps - int_part) : data->viewport.y;
771b2d0a103SDmytro Laktyushkin 			data->viewport.y -= int_adj;
772b2d0a103SDmytro Laktyushkin 			data->viewport.height += int_adj;
773b2d0a103SDmytro Laktyushkin 			int_part += int_adj;
774b2d0a103SDmytro Laktyushkin 		} else if (int_part > data->taps.v_taps) {
775b2d0a103SDmytro Laktyushkin 			data->viewport.y += int_part - data->taps.v_taps;
776b2d0a103SDmytro Laktyushkin 			data->viewport.height -= int_part - data->taps.v_taps;
777b2d0a103SDmytro Laktyushkin 			int_part = data->taps.v_taps;
778b2d0a103SDmytro Laktyushkin 		}
779b2d0a103SDmytro Laktyushkin 		data->inits.v.value &= 0xffffffff;
780b2d0a103SDmytro Laktyushkin 		data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part);
781b2d0a103SDmytro Laktyushkin 	}
782b2d0a103SDmytro Laktyushkin 
783b2d0a103SDmytro Laktyushkin 	if (data->viewport_c.y) {
784b2d0a103SDmytro Laktyushkin 		int int_part;
785b2d0a103SDmytro Laktyushkin 
786b2d0a103SDmytro Laktyushkin 		data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int(
787b2d0a103SDmytro Laktyushkin 				data->ratios.vert_c, recout_skip->height));
788b2d0a103SDmytro Laktyushkin 		int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y;
789b2d0a103SDmytro Laktyushkin 		if (int_part < data->taps.v_taps_c) {
790b2d0a103SDmytro Laktyushkin 			int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ?
791b2d0a103SDmytro Laktyushkin 					(data->taps.v_taps_c - int_part) : data->viewport_c.y;
792b2d0a103SDmytro Laktyushkin 			data->viewport_c.y -= int_adj;
793b2d0a103SDmytro Laktyushkin 			data->viewport_c.height += int_adj;
794b2d0a103SDmytro Laktyushkin 			int_part += int_adj;
795b2d0a103SDmytro Laktyushkin 		} else if (int_part > data->taps.v_taps_c) {
796b2d0a103SDmytro Laktyushkin 			data->viewport_c.y += int_part - data->taps.v_taps_c;
797b2d0a103SDmytro Laktyushkin 			data->viewport_c.height -= int_part - data->taps.v_taps_c;
798b2d0a103SDmytro Laktyushkin 			int_part = data->taps.v_taps_c;
799b2d0a103SDmytro Laktyushkin 		}
800b2d0a103SDmytro Laktyushkin 		data->inits.v_c.value &= 0xffffffff;
801b2d0a103SDmytro Laktyushkin 		data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part);
802b2d0a103SDmytro Laktyushkin 	}
803b2d0a103SDmytro Laktyushkin 
804b2d0a103SDmytro Laktyushkin 	/* Interlaced inits based on final vert inits */
805b2d0a103SDmytro Laktyushkin 	data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert);
806b2d0a103SDmytro Laktyushkin 	data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c);
8071fbd2cfcSDmytro Laktyushkin 
8083be5262eSHarry Wentland 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
8093be5262eSHarry Wentland 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
8101fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport_c);
8111fbd2cfcSDmytro Laktyushkin 		rect_swap_helper(&data->viewport);
8121fbd2cfcSDmytro Laktyushkin 	}
813b2d0a103SDmytro Laktyushkin }
814b2d0a103SDmytro Laktyushkin 
815b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
816b2d0a103SDmytro Laktyushkin {
8173be5262eSHarry Wentland 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
8184fa086b9SLeo (Sunpeng) Li 	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
819b2d0a103SDmytro Laktyushkin 	struct view recout_skip = { 0 };
820b2d0a103SDmytro Laktyushkin 	bool res = false;
821b2d0a103SDmytro Laktyushkin 
8224562236bSHarry Wentland 	/* Important: scaling ratio calculation requires pixel format,
8234562236bSHarry Wentland 	 * lb depth calculation requires recout and taps require scaling ratios.
824b2d0a103SDmytro Laktyushkin 	 * Inits require viewport, taps, ratios and recout of split pipe
8254562236bSHarry Wentland 	 */
8266702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
8273be5262eSHarry Wentland 			pipe_ctx->plane_state->format);
8284562236bSHarry Wentland 
829b2d0a103SDmytro Laktyushkin 	calculate_scaling_ratios(pipe_ctx);
830b2d0a103SDmytro Laktyushkin 
831b2d0a103SDmytro Laktyushkin 	calculate_viewport(pipe_ctx);
8324562236bSHarry Wentland 
8336702a9acSHarry Wentland 	if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16)
8344562236bSHarry Wentland 		return false;
8354562236bSHarry Wentland 
836b2d0a103SDmytro Laktyushkin 	calculate_recout(pipe_ctx, &recout_skip);
8374562236bSHarry Wentland 
8384562236bSHarry Wentland 	/**
8394562236bSHarry Wentland 	 * Setting line buffer pixel depth to 24bpp yields banding
8404562236bSHarry Wentland 	 * on certain displays, such as the Sharp 4k
8414562236bSHarry Wentland 	 */
8426702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
8434562236bSHarry Wentland 
8446702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable;
8456702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable;
8464562236bSHarry Wentland 
8474562236bSHarry Wentland 	/* Taps calculations */
84886a66c4eSHarry Wentland 	res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
84986a66c4eSHarry Wentland 		pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
8504562236bSHarry Wentland 
8514562236bSHarry Wentland 	if (!res) {
8524562236bSHarry Wentland 		/* Try 24 bpp linebuffer */
8536702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
8544562236bSHarry Wentland 
85586a66c4eSHarry Wentland 		res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
85686a66c4eSHarry Wentland 			pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
8574562236bSHarry Wentland 	}
8584562236bSHarry Wentland 
859b2d0a103SDmytro Laktyushkin 	if (res)
8601fbd2cfcSDmytro Laktyushkin 		/* May need to re-check lb size after this in some obscure scenario */
861b2d0a103SDmytro Laktyushkin 		calculate_inits_and_adj_vp(pipe_ctx, &recout_skip);
862b2d0a103SDmytro Laktyushkin 
8634562236bSHarry Wentland 	dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
8644562236bSHarry Wentland 				"%s: Viewport:\nheight:%d width:%d x:%d "
8654562236bSHarry Wentland 				"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
8664562236bSHarry Wentland 				"y:%d\n",
8674562236bSHarry Wentland 				__func__,
8686702a9acSHarry Wentland 				pipe_ctx->plane_res.scl_data.viewport.height,
8696702a9acSHarry Wentland 				pipe_ctx->plane_res.scl_data.viewport.width,
8706702a9acSHarry Wentland 				pipe_ctx->plane_res.scl_data.viewport.x,
8716702a9acSHarry Wentland 				pipe_ctx->plane_res.scl_data.viewport.y,
8723be5262eSHarry Wentland 				plane_state->dst_rect.height,
8733be5262eSHarry Wentland 				plane_state->dst_rect.width,
8743be5262eSHarry Wentland 				plane_state->dst_rect.x,
8753be5262eSHarry Wentland 				plane_state->dst_rect.y);
8764562236bSHarry Wentland 
8774562236bSHarry Wentland 	return res;
8784562236bSHarry Wentland }
8794562236bSHarry Wentland 
8804562236bSHarry Wentland 
8814562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context(
8824562236bSHarry Wentland 	const struct core_dc *dc,
8834562236bSHarry Wentland 	struct validate_context *context)
8844562236bSHarry Wentland {
8854562236bSHarry Wentland 	int i;
8864562236bSHarry Wentland 
8874562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
8883be5262eSHarry Wentland 		if (context->res_ctx.pipe_ctx[i].plane_state != NULL &&
8894562236bSHarry Wentland 				context->res_ctx.pipe_ctx[i].stream != NULL)
890b2d0a103SDmytro Laktyushkin 			if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i]))
891f84a8161STony Cheng 				return DC_FAIL_SCALING;
8924562236bSHarry Wentland 	}
8934562236bSHarry Wentland 
8944562236bSHarry Wentland 	return DC_OK;
8954562236bSHarry Wentland }
8964562236bSHarry Wentland 
897a2b8659dSTony Cheng struct pipe_ctx *find_idle_secondary_pipe(
898a2b8659dSTony Cheng 		struct resource_context *res_ctx,
899a2b8659dSTony Cheng 		const struct resource_pool *pool)
9004562236bSHarry Wentland {
9014562236bSHarry Wentland 	int i;
9024562236bSHarry Wentland 	struct pipe_ctx *secondary_pipe = NULL;
9034562236bSHarry Wentland 
9044562236bSHarry Wentland 	/*
9054562236bSHarry Wentland 	 * search backwards for the second pipe to keep pipe
9064562236bSHarry Wentland 	 * assignment more consistent
9074562236bSHarry Wentland 	 */
9084562236bSHarry Wentland 
909a2b8659dSTony Cheng 	for (i = pool->pipe_count - 1; i >= 0; i--) {
9104562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == NULL) {
9114562236bSHarry Wentland 			secondary_pipe = &res_ctx->pipe_ctx[i];
9124562236bSHarry Wentland 			secondary_pipe->pipe_idx = i;
9134562236bSHarry Wentland 			break;
9144562236bSHarry Wentland 		}
9154562236bSHarry Wentland 	}
9164562236bSHarry Wentland 
9174562236bSHarry Wentland 
9184562236bSHarry Wentland 	return secondary_pipe;
9194562236bSHarry Wentland }
9204562236bSHarry Wentland 
9214562236bSHarry Wentland struct pipe_ctx *resource_get_head_pipe_for_stream(
9224562236bSHarry Wentland 		struct resource_context *res_ctx,
9230971c40eSHarry Wentland 		struct dc_stream_state *stream)
9244562236bSHarry Wentland {
9254562236bSHarry Wentland 	int i;
926a2b8659dSTony Cheng 	for (i = 0; i < MAX_PIPES; i++) {
9274562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
9288e9c4c8cSHarry Wentland 				res_ctx->pipe_ctx[i].stream_res.stream_enc) {
9294562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
9304562236bSHarry Wentland 			break;
9314562236bSHarry Wentland 		}
9324562236bSHarry Wentland 	}
9334562236bSHarry Wentland 	return NULL;
9344562236bSHarry Wentland }
9354562236bSHarry Wentland 
9364562236bSHarry Wentland /*
937ab2541b6SAric Cyr  * A free_pipe for a stream is defined here as a pipe
938ab2541b6SAric Cyr  * that has no surface attached yet
9394562236bSHarry Wentland  */
940ab2541b6SAric Cyr static struct pipe_ctx *acquire_free_pipe_for_stream(
941745cc746SDmytro Laktyushkin 		struct validate_context *context,
942a2b8659dSTony Cheng 		const struct resource_pool *pool,
9430971c40eSHarry Wentland 		struct dc_stream_state *stream)
9444562236bSHarry Wentland {
9454562236bSHarry Wentland 	int i;
946745cc746SDmytro Laktyushkin 	struct resource_context *res_ctx = &context->res_ctx;
9474562236bSHarry Wentland 
9484562236bSHarry Wentland 	struct pipe_ctx *head_pipe = NULL;
9494562236bSHarry Wentland 
9504562236bSHarry Wentland 	/* Find head pipe, which has the back end set up*/
9514562236bSHarry Wentland 
9524562236bSHarry Wentland 	head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
9534562236bSHarry Wentland 
9544562236bSHarry Wentland 	if (!head_pipe)
9554562236bSHarry Wentland 		ASSERT(0);
9564562236bSHarry Wentland 
9573be5262eSHarry Wentland 	if (!head_pipe->plane_state)
9584562236bSHarry Wentland 		return head_pipe;
9594562236bSHarry Wentland 
9604562236bSHarry Wentland 	/* Re-use pipe already acquired for this stream if available*/
961a2b8659dSTony Cheng 	for (i = pool->pipe_count - 1; i >= 0; i--) {
9624562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
9633be5262eSHarry Wentland 				!res_ctx->pipe_ctx[i].plane_state) {
9644562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
9654562236bSHarry Wentland 		}
9664562236bSHarry Wentland 	}
9674562236bSHarry Wentland 
9684562236bSHarry Wentland 	/*
9694562236bSHarry Wentland 	 * At this point we have no re-useable pipe for this stream and we need
9704562236bSHarry Wentland 	 * to acquire an idle one to satisfy the request
9714562236bSHarry Wentland 	 */
9724562236bSHarry Wentland 
973a2b8659dSTony Cheng 	if (!pool->funcs->acquire_idle_pipe_for_layer)
9744562236bSHarry Wentland 		return NULL;
9754562236bSHarry Wentland 
976a2b8659dSTony Cheng 	return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream);
9774562236bSHarry Wentland 
9784562236bSHarry Wentland }
9794562236bSHarry Wentland 
980ab2541b6SAric Cyr static void release_free_pipes_for_stream(
9814562236bSHarry Wentland 		struct resource_context *res_ctx,
9820971c40eSHarry Wentland 		struct dc_stream_state *stream)
9834562236bSHarry Wentland {
9844562236bSHarry Wentland 	int i;
9854562236bSHarry Wentland 
986a2b8659dSTony Cheng 	for (i = MAX_PIPES - 1; i >= 0; i--) {
98705a19c39SDmytro Laktyushkin 		/* never release the topmost pipe*/
9884562236bSHarry Wentland 		if (res_ctx->pipe_ctx[i].stream == stream &&
98905a19c39SDmytro Laktyushkin 				res_ctx->pipe_ctx[i].top_pipe &&
9903be5262eSHarry Wentland 				!res_ctx->pipe_ctx[i].plane_state) {
99105a19c39SDmytro Laktyushkin 			memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx));
9924562236bSHarry Wentland 		}
9934562236bSHarry Wentland 	}
9944562236bSHarry Wentland }
9954562236bSHarry Wentland 
9960f9a536fSDmytro Laktyushkin #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
9970f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe(
9980f9a536fSDmytro Laktyushkin 		struct resource_context *res_ctx,
9990f9a536fSDmytro Laktyushkin 		const struct resource_pool *pool,
10000971c40eSHarry Wentland 		struct dc_stream_state *stream)
10010f9a536fSDmytro Laktyushkin {
10020f9a536fSDmytro Laktyushkin 	int i;
10030f9a536fSDmytro Laktyushkin 
10040f9a536fSDmytro Laktyushkin 	for (i = 0; i < pool->pipe_count; i++) {
10050f9a536fSDmytro Laktyushkin 		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
10060f9a536fSDmytro Laktyushkin 
10070f9a536fSDmytro Laktyushkin 		if (pipe_ctx->top_pipe &&
10083be5262eSHarry Wentland 				pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) {
10090f9a536fSDmytro Laktyushkin 			pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
10100f9a536fSDmytro Laktyushkin 			if (pipe_ctx->bottom_pipe)
10110f9a536fSDmytro Laktyushkin 				pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
10120f9a536fSDmytro Laktyushkin 
10130f9a536fSDmytro Laktyushkin 			memset(pipe_ctx, 0, sizeof(*pipe_ctx));
10146b670fa9SHarry Wentland 			pipe_ctx->stream_res.tg = pool->timing_generators[i];
101586a66c4eSHarry Wentland 			pipe_ctx->plane_res.mi = pool->mis[i];
101686a66c4eSHarry Wentland 			pipe_ctx->plane_res.ipp = pool->ipps[i];
101786a66c4eSHarry Wentland 			pipe_ctx->plane_res.xfm = pool->transforms[i];
1018a6a6cb34SHarry Wentland 			pipe_ctx->stream_res.opp = pool->opps[i];
10190f9a536fSDmytro Laktyushkin 			pipe_ctx->dis_clk = pool->display_clock;
10200f9a536fSDmytro Laktyushkin 			pipe_ctx->pipe_idx = i;
10210f9a536fSDmytro Laktyushkin 
10220f9a536fSDmytro Laktyushkin 			pipe_ctx->stream = stream;
10230f9a536fSDmytro Laktyushkin 			return i;
10240f9a536fSDmytro Laktyushkin 		}
10250f9a536fSDmytro Laktyushkin 	}
10260f9a536fSDmytro Laktyushkin 	return -1;
10270f9a536fSDmytro Laktyushkin }
10280f9a536fSDmytro Laktyushkin #endif
10290f9a536fSDmytro Laktyushkin 
10304562236bSHarry Wentland bool resource_attach_surfaces_to_context(
10313be5262eSHarry Wentland 		struct dc_plane_state * const *plane_states,
10324562236bSHarry Wentland 		int surface_count,
10330971c40eSHarry Wentland 		struct dc_stream_state *stream,
1034a2b8659dSTony Cheng 		struct validate_context *context,
1035a2b8659dSTony Cheng 		const struct resource_pool *pool)
10364562236bSHarry Wentland {
10374562236bSHarry Wentland 	int i;
10384562236bSHarry Wentland 	struct pipe_ctx *tail_pipe;
1039ab2541b6SAric Cyr 	struct dc_stream_status *stream_status = NULL;
10404562236bSHarry Wentland 
10414562236bSHarry Wentland 
10424562236bSHarry Wentland 	if (surface_count > MAX_SURFACE_NUM) {
10434562236bSHarry Wentland 		dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
10444562236bSHarry Wentland 			surface_count, MAX_SURFACE_NUM);
10454562236bSHarry Wentland 		return false;
10464562236bSHarry Wentland 	}
10474562236bSHarry Wentland 
1048ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++)
10494fa086b9SLeo (Sunpeng) Li 		if (context->streams[i] == stream) {
1050ab2541b6SAric Cyr 			stream_status = &context->stream_status[i];
10514562236bSHarry Wentland 			break;
10524562236bSHarry Wentland 		}
1053ab2541b6SAric Cyr 	if (stream_status == NULL) {
1054ab2541b6SAric Cyr 		dm_error("Existing stream not found; failed to attach surfaces\n");
10554562236bSHarry Wentland 		return false;
10564562236bSHarry Wentland 	}
10574562236bSHarry Wentland 
10584562236bSHarry Wentland 	/* retain new surfaces */
10594562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
10603be5262eSHarry Wentland 		dc_plane_state_retain(plane_states[i]);
10614562236bSHarry Wentland 
106205a19c39SDmytro Laktyushkin 	/* detach surfaces from pipes */
106305a19c39SDmytro Laktyushkin 	for (i = 0; i < pool->pipe_count; i++)
106405a19c39SDmytro Laktyushkin 		if (context->res_ctx.pipe_ctx[i].stream == stream) {
10653be5262eSHarry Wentland 			context->res_ctx.pipe_ctx[i].plane_state = NULL;
106605a19c39SDmytro Laktyushkin 			context->res_ctx.pipe_ctx[i].bottom_pipe = NULL;
106705a19c39SDmytro Laktyushkin 		}
10684562236bSHarry Wentland 
10694562236bSHarry Wentland 	/* release existing surfaces*/
10703be5262eSHarry Wentland 	for (i = 0; i < stream_status->plane_count; i++)
10713be5262eSHarry Wentland 		dc_plane_state_release(stream_status->plane_states[i]);
10724562236bSHarry Wentland 
10733be5262eSHarry Wentland 	for (i = surface_count; i < stream_status->plane_count; i++)
10743be5262eSHarry Wentland 		stream_status->plane_states[i] = NULL;
10754562236bSHarry Wentland 
10764562236bSHarry Wentland 	tail_pipe = NULL;
10774562236bSHarry Wentland 	for (i = 0; i < surface_count; i++) {
10783be5262eSHarry Wentland 		struct dc_plane_state *plane_state = plane_states[i];
1079a2b8659dSTony Cheng 		struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(
10804fa086b9SLeo (Sunpeng) Li 				context, pool, stream);
10814562236bSHarry Wentland 
10820f9a536fSDmytro Laktyushkin #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
10830f9a536fSDmytro Laktyushkin 		if (!free_pipe) {
10840f9a536fSDmytro Laktyushkin 			int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
10850f9a536fSDmytro Laktyushkin 			if (pipe_idx >= 0)
10860f9a536fSDmytro Laktyushkin 				free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
10870f9a536fSDmytro Laktyushkin 		}
10880f9a536fSDmytro Laktyushkin #endif
10894562236bSHarry Wentland 		if (!free_pipe) {
10903be5262eSHarry Wentland 			stream_status->plane_states[i] = NULL;
10914562236bSHarry Wentland 			return false;
10924562236bSHarry Wentland 		}
10934562236bSHarry Wentland 
10943be5262eSHarry Wentland 		free_pipe->plane_state = plane_state;
10954562236bSHarry Wentland 
10964562236bSHarry Wentland 		if (tail_pipe) {
10976b670fa9SHarry Wentland 			free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
1098a6a6cb34SHarry Wentland 			free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
10998e9c4c8cSHarry Wentland 			free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
1100cfe4645eSDmytro Laktyushkin 			free_pipe->audio = tail_pipe->audio;
1101cfe4645eSDmytro Laktyushkin 			free_pipe->clock_source = tail_pipe->clock_source;
11024562236bSHarry Wentland 			free_pipe->top_pipe = tail_pipe;
11034562236bSHarry Wentland 			tail_pipe->bottom_pipe = free_pipe;
11044562236bSHarry Wentland 		}
11054562236bSHarry Wentland 
11064562236bSHarry Wentland 		tail_pipe = free_pipe;
11074562236bSHarry Wentland 	}
11084562236bSHarry Wentland 
11094fa086b9SLeo (Sunpeng) Li 	release_free_pipes_for_stream(&context->res_ctx, stream);
11104562236bSHarry Wentland 
11114562236bSHarry Wentland 	/* assign new surfaces*/
11124562236bSHarry Wentland 	for (i = 0; i < surface_count; i++)
11133be5262eSHarry Wentland 		stream_status->plane_states[i] = plane_states[i];
11144562236bSHarry Wentland 
11153be5262eSHarry Wentland 	stream_status->plane_count = surface_count;
11164562236bSHarry Wentland 
11174562236bSHarry Wentland 	return true;
11184562236bSHarry Wentland }
11194562236bSHarry Wentland 
11204562236bSHarry Wentland 
11210971c40eSHarry Wentland static bool is_timing_changed(struct dc_stream_state *cur_stream,
11220971c40eSHarry Wentland 		struct dc_stream_state *new_stream)
11234562236bSHarry Wentland {
11244562236bSHarry Wentland 	if (cur_stream == NULL)
11254562236bSHarry Wentland 		return true;
11264562236bSHarry Wentland 
11274562236bSHarry Wentland 	/* If sink pointer changed, it means this is a hotplug, we should do
11284562236bSHarry Wentland 	 * full hw setting.
11294562236bSHarry Wentland 	 */
11304562236bSHarry Wentland 	if (cur_stream->sink != new_stream->sink)
11314562236bSHarry Wentland 		return true;
11324562236bSHarry Wentland 
11334562236bSHarry Wentland 	/* If output color space is changed, need to reprogram info frames */
11344fa086b9SLeo (Sunpeng) Li 	if (cur_stream->output_color_space != new_stream->output_color_space)
11354562236bSHarry Wentland 		return true;
11364562236bSHarry Wentland 
11374562236bSHarry Wentland 	return memcmp(
11384fa086b9SLeo (Sunpeng) Li 		&cur_stream->timing,
11394fa086b9SLeo (Sunpeng) Li 		&new_stream->timing,
11404562236bSHarry Wentland 		sizeof(struct dc_crtc_timing)) != 0;
11414562236bSHarry Wentland }
11424562236bSHarry Wentland 
11434562236bSHarry Wentland static bool are_stream_backends_same(
11440971c40eSHarry Wentland 	struct dc_stream_state *stream_a, struct dc_stream_state *stream_b)
11454562236bSHarry Wentland {
11464562236bSHarry Wentland 	if (stream_a == stream_b)
11474562236bSHarry Wentland 		return true;
11484562236bSHarry Wentland 
11494562236bSHarry Wentland 	if (stream_a == NULL || stream_b == NULL)
11504562236bSHarry Wentland 		return false;
11514562236bSHarry Wentland 
11524562236bSHarry Wentland 	if (is_timing_changed(stream_a, stream_b))
11534562236bSHarry Wentland 		return false;
11544562236bSHarry Wentland 
11554562236bSHarry Wentland 	return true;
11564562236bSHarry Wentland }
11574562236bSHarry Wentland 
1158d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged(
11590971c40eSHarry Wentland 	struct dc_stream_state *old_stream, struct dc_stream_state *stream)
11604562236bSHarry Wentland {
11614562236bSHarry Wentland 
11624562236bSHarry Wentland 	if (!are_stream_backends_same(old_stream, stream))
11634562236bSHarry Wentland 		return false;
11644562236bSHarry Wentland 
11654562236bSHarry Wentland 	return true;
11664562236bSHarry Wentland }
11674562236bSHarry Wentland 
11684562236bSHarry Wentland bool resource_validate_attach_surfaces(
11694562236bSHarry Wentland 		const struct dc_validation_set set[],
11704562236bSHarry Wentland 		int set_count,
11714562236bSHarry Wentland 		const struct validate_context *old_context,
1172a2b8659dSTony Cheng 		struct validate_context *context,
1173a2b8659dSTony Cheng 		const struct resource_pool *pool)
11744562236bSHarry Wentland {
11754562236bSHarry Wentland 	int i, j;
11764562236bSHarry Wentland 
11774562236bSHarry Wentland 	for (i = 0; i < set_count; i++) {
1178430ef426SDmytro Laktyushkin 		for (j = 0; old_context && j < old_context->stream_count; j++)
1179d54d29dbSBhawanpreet Lakha 			if (dc_is_stream_unchanged(
1180ab2541b6SAric Cyr 					old_context->streams[j],
1181ab2541b6SAric Cyr 					context->streams[i])) {
11824562236bSHarry Wentland 				if (!resource_attach_surfaces_to_context(
11833be5262eSHarry Wentland 						old_context->stream_status[j].plane_states,
11843be5262eSHarry Wentland 						old_context->stream_status[j].plane_count,
11854fa086b9SLeo (Sunpeng) Li 						context->streams[i],
1186a2b8659dSTony Cheng 						context, pool))
11874562236bSHarry Wentland 					return false;
1188ab2541b6SAric Cyr 				context->stream_status[i] = old_context->stream_status[j];
11894562236bSHarry Wentland 			}
11903be5262eSHarry Wentland 		if (set[i].plane_count != 0)
11914562236bSHarry Wentland 			if (!resource_attach_surfaces_to_context(
11923be5262eSHarry Wentland 					set[i].plane_states,
11933be5262eSHarry Wentland 					set[i].plane_count,
11944fa086b9SLeo (Sunpeng) Li 					context->streams[i],
1195a2b8659dSTony Cheng 					context, pool))
11964562236bSHarry Wentland 				return false;
11974562236bSHarry Wentland 
11984562236bSHarry Wentland 	}
11994562236bSHarry Wentland 
12004562236bSHarry Wentland 	return true;
12014562236bSHarry Wentland }
12024562236bSHarry Wentland 
12034562236bSHarry Wentland /* Maximum TMDS single link pixel clock 165MHz */
12044562236bSHarry Wentland #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
1205909e8c9eSCharlene Liu #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000
12064562236bSHarry Wentland 
12074562236bSHarry Wentland static void set_stream_engine_in_use(
12084562236bSHarry Wentland 		struct resource_context *res_ctx,
1209a2b8659dSTony Cheng 		const struct resource_pool *pool,
12104562236bSHarry Wentland 		struct stream_encoder *stream_enc)
12114562236bSHarry Wentland {
12124562236bSHarry Wentland 	int i;
12134562236bSHarry Wentland 
1214a2b8659dSTony Cheng 	for (i = 0; i < pool->stream_enc_count; i++) {
1215a2b8659dSTony Cheng 		if (pool->stream_enc[i] == stream_enc)
12164562236bSHarry Wentland 			res_ctx->is_stream_enc_acquired[i] = true;
12174562236bSHarry Wentland 	}
12184562236bSHarry Wentland }
12194562236bSHarry Wentland 
12204562236bSHarry Wentland /* TODO: release audio object */
12214562236bSHarry Wentland static void set_audio_in_use(
12224562236bSHarry Wentland 		struct resource_context *res_ctx,
1223a2b8659dSTony Cheng 		const struct resource_pool *pool,
12244562236bSHarry Wentland 		struct audio *audio)
12254562236bSHarry Wentland {
12264562236bSHarry Wentland 	int i;
1227a2b8659dSTony Cheng 	for (i = 0; i < pool->audio_count; i++) {
1228a2b8659dSTony Cheng 		if (pool->audios[i] == audio)
12294562236bSHarry Wentland 			res_ctx->is_audio_acquired[i] = true;
12304562236bSHarry Wentland 	}
12314562236bSHarry Wentland }
12324562236bSHarry Wentland 
12334562236bSHarry Wentland static int acquire_first_free_pipe(
12344562236bSHarry Wentland 		struct resource_context *res_ctx,
1235a2b8659dSTony Cheng 		const struct resource_pool *pool,
12360971c40eSHarry Wentland 		struct dc_stream_state *stream)
12374562236bSHarry Wentland {
12384562236bSHarry Wentland 	int i;
12394562236bSHarry Wentland 
1240a2b8659dSTony Cheng 	for (i = 0; i < pool->pipe_count; i++) {
12414562236bSHarry Wentland 		if (!res_ctx->pipe_ctx[i].stream) {
12424562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
12434562236bSHarry Wentland 
12446b670fa9SHarry Wentland 			pipe_ctx->stream_res.tg = pool->timing_generators[i];
124586a66c4eSHarry Wentland 			pipe_ctx->plane_res.mi = pool->mis[i];
124686a66c4eSHarry Wentland 			pipe_ctx->plane_res.ipp = pool->ipps[i];
124786a66c4eSHarry Wentland 			pipe_ctx->plane_res.xfm = pool->transforms[i];
1248a6a6cb34SHarry Wentland 			pipe_ctx->stream_res.opp = pool->opps[i];
1249a2b8659dSTony Cheng 			pipe_ctx->dis_clk = pool->display_clock;
12504562236bSHarry Wentland 			pipe_ctx->pipe_idx = i;
12514562236bSHarry Wentland 
1252ff5ef992SAlex Deucher 
12534562236bSHarry Wentland 			pipe_ctx->stream = stream;
12544562236bSHarry Wentland 			return i;
12554562236bSHarry Wentland 		}
12564562236bSHarry Wentland 	}
12574562236bSHarry Wentland 	return -1;
12584562236bSHarry Wentland }
12594562236bSHarry Wentland 
12604562236bSHarry Wentland static struct stream_encoder *find_first_free_match_stream_enc_for_link(
12614562236bSHarry Wentland 		struct resource_context *res_ctx,
1262a2b8659dSTony Cheng 		const struct resource_pool *pool,
12630971c40eSHarry Wentland 		struct dc_stream_state *stream)
12644562236bSHarry Wentland {
12654562236bSHarry Wentland 	int i;
12664562236bSHarry Wentland 	int j = -1;
1267d0778ebfSHarry Wentland 	struct dc_link *link = stream->sink->link;
12684562236bSHarry Wentland 
1269a2b8659dSTony Cheng 	for (i = 0; i < pool->stream_enc_count; i++) {
12704562236bSHarry Wentland 		if (!res_ctx->is_stream_enc_acquired[i] &&
1271a2b8659dSTony Cheng 				pool->stream_enc[i]) {
12724562236bSHarry Wentland 			/* Store first available for MST second display
12734562236bSHarry Wentland 			 * in daisy chain use case */
12744562236bSHarry Wentland 			j = i;
1275a2b8659dSTony Cheng 			if (pool->stream_enc[i]->id ==
12764562236bSHarry Wentland 					link->link_enc->preferred_engine)
1277a2b8659dSTony Cheng 				return pool->stream_enc[i];
12784562236bSHarry Wentland 		}
12794562236bSHarry Wentland 	}
12804562236bSHarry Wentland 
12814562236bSHarry Wentland 	/*
12824562236bSHarry Wentland 	 * below can happen in cases when stream encoder is acquired:
12834562236bSHarry Wentland 	 * 1) for second MST display in chain, so preferred engine already
12844562236bSHarry Wentland 	 * acquired;
12854562236bSHarry Wentland 	 * 2) for another link, which preferred engine already acquired by any
12864562236bSHarry Wentland 	 * MST configuration.
12874562236bSHarry Wentland 	 *
12884562236bSHarry Wentland 	 * If signal is of DP type and preferred engine not found, return last available
12894562236bSHarry Wentland 	 *
12904562236bSHarry Wentland 	 * TODO - This is just a patch up and a generic solution is
12914562236bSHarry Wentland 	 * required for non DP connectors.
12924562236bSHarry Wentland 	 */
12934562236bSHarry Wentland 
12944562236bSHarry Wentland 	if (j >= 0 && dc_is_dp_signal(stream->signal))
1295a2b8659dSTony Cheng 		return pool->stream_enc[j];
12964562236bSHarry Wentland 
12974562236bSHarry Wentland 	return NULL;
12984562236bSHarry Wentland }
12994562236bSHarry Wentland 
1300a2b8659dSTony Cheng static struct audio *find_first_free_audio(
1301a2b8659dSTony Cheng 		struct resource_context *res_ctx,
1302a2b8659dSTony Cheng 		const struct resource_pool *pool)
13034562236bSHarry Wentland {
13044562236bSHarry Wentland 	int i;
1305a2b8659dSTony Cheng 	for (i = 0; i < pool->audio_count; i++) {
13064562236bSHarry Wentland 		if (res_ctx->is_audio_acquired[i] == false) {
1307a2b8659dSTony Cheng 			return pool->audios[i];
13084562236bSHarry Wentland 		}
13094562236bSHarry Wentland 	}
13104562236bSHarry Wentland 
13114562236bSHarry Wentland 	return 0;
13124562236bSHarry Wentland }
13134562236bSHarry Wentland 
13140971c40eSHarry Wentland static void update_stream_signal(struct dc_stream_state *stream)
13154562236bSHarry Wentland {
13164fa086b9SLeo (Sunpeng) Li 	if (stream->output_signal == SIGNAL_TYPE_NONE) {
13174fa086b9SLeo (Sunpeng) Li 		struct dc_sink *dc_sink = stream->sink;
13184562236bSHarry Wentland 
13192796eaeeSJoshua Aberback 		if (dc_sink->sink_signal == SIGNAL_TYPE_NONE)
1320d0778ebfSHarry Wentland 			stream->signal = stream->sink->link->connector_signal;
13212796eaeeSJoshua Aberback 		else
13222796eaeeSJoshua Aberback 			stream->signal = dc_sink->sink_signal;
13238b32076cSSylvia Tsai 	} else {
13244fa086b9SLeo (Sunpeng) Li 		stream->signal = stream->output_signal;
13258b32076cSSylvia Tsai 	}
13268b32076cSSylvia Tsai 
132756dcade3SHarry Wentland 	if (dc_is_dvi_signal(stream->signal)) {
13284fa086b9SLeo (Sunpeng) Li 		if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST &&
13294fa086b9SLeo (Sunpeng) Li 			stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
13308b32076cSSylvia Tsai 			stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
133156dcade3SHarry Wentland 		else
133256dcade3SHarry Wentland 			stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
133356dcade3SHarry Wentland 	}
13344562236bSHarry Wentland }
13354562236bSHarry Wentland 
13364562236bSHarry Wentland bool resource_is_stream_unchanged(
13370971c40eSHarry Wentland 	struct validate_context *old_context, struct dc_stream_state *stream)
13384562236bSHarry Wentland {
1339ab2541b6SAric Cyr 	int i;
13404562236bSHarry Wentland 
1341ab2541b6SAric Cyr 	for (i = 0; i < old_context->stream_count; i++) {
13420971c40eSHarry Wentland 		struct dc_stream_state *old_stream = old_context->streams[i];
13434562236bSHarry Wentland 
13444562236bSHarry Wentland 		if (are_stream_backends_same(old_stream, stream))
13454562236bSHarry Wentland 				return true;
13464562236bSHarry Wentland 	}
13474562236bSHarry Wentland 
13484562236bSHarry Wentland 	return false;
13494562236bSHarry Wentland }
13504562236bSHarry Wentland 
13514562236bSHarry Wentland static void copy_pipe_ctx(
13524562236bSHarry Wentland 	const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
13534562236bSHarry Wentland {
13543be5262eSHarry Wentland 	struct dc_plane_state *plane_state = to_pipe_ctx->plane_state;
13550971c40eSHarry Wentland 	struct dc_stream_state *stream = to_pipe_ctx->stream;
13564562236bSHarry Wentland 
13574562236bSHarry Wentland 	*to_pipe_ctx = *from_pipe_ctx;
13584562236bSHarry Wentland 	to_pipe_ctx->stream = stream;
13593be5262eSHarry Wentland 	if (plane_state != NULL)
13603be5262eSHarry Wentland 		to_pipe_ctx->plane_state = plane_state;
13614562236bSHarry Wentland }
13624562236bSHarry Wentland 
13630971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream(
13640971c40eSHarry Wentland 		struct dc_stream_state *stream_needs_pll,
13654562236bSHarry Wentland 		struct validate_context *context)
13664562236bSHarry Wentland {
1367ab2541b6SAric Cyr 	int i;
13684562236bSHarry Wentland 
1369ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
13700971c40eSHarry Wentland 		struct dc_stream_state *stream_has_pll = context->streams[i];
13714562236bSHarry Wentland 
13724562236bSHarry Wentland 		/* We are looking for non dp, non virtual stream */
13734562236bSHarry Wentland 		if (resource_are_streams_timing_synchronizable(
13744562236bSHarry Wentland 			stream_needs_pll, stream_has_pll)
13754562236bSHarry Wentland 			&& !dc_is_dp_signal(stream_has_pll->signal)
1376d0778ebfSHarry Wentland 			&& stream_has_pll->sink->link->connector_signal
13774562236bSHarry Wentland 			!= SIGNAL_TYPE_VIRTUAL)
13784562236bSHarry Wentland 			return stream_has_pll;
1379ab2541b6SAric Cyr 
13804562236bSHarry Wentland 	}
13814562236bSHarry Wentland 
13824562236bSHarry Wentland 	return NULL;
13834562236bSHarry Wentland }
13844562236bSHarry Wentland 
13854562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
13864562236bSHarry Wentland {
13874562236bSHarry Wentland 	uint32_t pix_clk = timing->pix_clk_khz;
13884562236bSHarry Wentland 	uint32_t normalized_pix_clk = pix_clk;
13894562236bSHarry Wentland 
13904562236bSHarry Wentland 	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
13914562236bSHarry Wentland 		pix_clk /= 2;
1392cc4d99b8SCharlene Liu 	if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
13934562236bSHarry Wentland 		switch (timing->display_color_depth) {
13944562236bSHarry Wentland 		case COLOR_DEPTH_888:
13954562236bSHarry Wentland 			normalized_pix_clk = pix_clk;
13964562236bSHarry Wentland 			break;
13974562236bSHarry Wentland 		case COLOR_DEPTH_101010:
13984562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 30) / 24;
13994562236bSHarry Wentland 			break;
14004562236bSHarry Wentland 		case COLOR_DEPTH_121212:
14014562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 36) / 24;
14024562236bSHarry Wentland 		break;
14034562236bSHarry Wentland 		case COLOR_DEPTH_161616:
14044562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 48) / 24;
14054562236bSHarry Wentland 		break;
14064562236bSHarry Wentland 		default:
14074562236bSHarry Wentland 			ASSERT(0);
14084562236bSHarry Wentland 		break;
14094562236bSHarry Wentland 		}
1410cc4d99b8SCharlene Liu 	}
14114562236bSHarry Wentland 	return normalized_pix_clk;
14124562236bSHarry Wentland }
14134562236bSHarry Wentland 
14140971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream)
14154562236bSHarry Wentland {
14164562236bSHarry Wentland 	update_stream_signal(stream);
14174562236bSHarry Wentland 
14184562236bSHarry Wentland 	/* update actual pixel clock on all streams */
14194562236bSHarry Wentland 	if (dc_is_hdmi_signal(stream->signal))
14204562236bSHarry Wentland 		stream->phy_pix_clk = get_norm_pix_clk(
14214fa086b9SLeo (Sunpeng) Li 			&stream->timing);
14224562236bSHarry Wentland 	else
14234562236bSHarry Wentland 		stream->phy_pix_clk =
14244fa086b9SLeo (Sunpeng) Li 			stream->timing.pix_clk_khz;
14254562236bSHarry Wentland }
14264562236bSHarry Wentland 
14274562236bSHarry Wentland enum dc_status resource_map_pool_resources(
14284562236bSHarry Wentland 		const struct core_dc *dc,
1429430ef426SDmytro Laktyushkin 		struct validate_context *context,
1430430ef426SDmytro Laktyushkin 		struct validate_context *old_context)
14314562236bSHarry Wentland {
1432a2b8659dSTony Cheng 	const struct resource_pool *pool = dc->res_pool;
1433ab2541b6SAric Cyr 	int i, j;
14344562236bSHarry Wentland 
1435430ef426SDmytro Laktyushkin 	for (i = 0; old_context && i < context->stream_count; i++) {
14360971c40eSHarry Wentland 		struct dc_stream_state *stream = context->streams[i];
14374562236bSHarry Wentland 
1438430ef426SDmytro Laktyushkin 		if (!resource_is_stream_unchanged(old_context, stream)) {
1439430ef426SDmytro Laktyushkin 			if (stream != NULL && old_context->streams[i] != NULL) {
14404b679bc3SCharlene Liu 				stream->bit_depth_params =
1441430ef426SDmytro Laktyushkin 						old_context->streams[i]->bit_depth_params;
1442430ef426SDmytro Laktyushkin 				stream->clamping = old_context->streams[i]->clamping;
14434562236bSHarry Wentland 				continue;
14444b679bc3SCharlene Liu 			}
14454b679bc3SCharlene Liu 		}
14467e2fe319SCharlene Liu 
14474562236bSHarry Wentland 		/* mark resources used for stream that is already active */
1448a2b8659dSTony Cheng 		for (j = 0; j < pool->pipe_count; j++) {
14494562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx =
1450ab2541b6SAric Cyr 				&context->res_ctx.pipe_ctx[j];
14514562236bSHarry Wentland 			const struct pipe_ctx *old_pipe_ctx =
1452430ef426SDmytro Laktyushkin 					&old_context->res_ctx.pipe_ctx[j];
14534562236bSHarry Wentland 
14544562236bSHarry Wentland 			if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
14554562236bSHarry Wentland 				continue;
14564562236bSHarry Wentland 
1457268cadbdSYongqiang Sun 			if (old_pipe_ctx->top_pipe)
1458268cadbdSYongqiang Sun 				continue;
1459268cadbdSYongqiang Sun 
14604562236bSHarry Wentland 			pipe_ctx->stream = stream;
14614562236bSHarry Wentland 			copy_pipe_ctx(old_pipe_ctx, pipe_ctx);
14624562236bSHarry Wentland 
14638c737fccSYongqiang Sun 			/* Split pipe resource, do not acquire back end */
14648e9c4c8cSHarry Wentland 			if (!pipe_ctx->stream_res.stream_enc)
14658c737fccSYongqiang Sun 				continue;
14668c737fccSYongqiang Sun 
14674562236bSHarry Wentland 			set_stream_engine_in_use(
1468a2b8659dSTony Cheng 				&context->res_ctx, pool,
14698e9c4c8cSHarry Wentland 				pipe_ctx->stream_res.stream_enc);
14704562236bSHarry Wentland 
14714562236bSHarry Wentland 			/* Switch to dp clock source only if there is
14724562236bSHarry Wentland 			 * no non dp stream that shares the same timing
14734562236bSHarry Wentland 			 * with the dp stream.
14744562236bSHarry Wentland 			 */
14754562236bSHarry Wentland 			if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
14764562236bSHarry Wentland 				!find_pll_sharable_stream(stream, context))
1477a2b8659dSTony Cheng 				pipe_ctx->clock_source = pool->dp_clock_source;
14784562236bSHarry Wentland 
14794562236bSHarry Wentland 			resource_reference_clock_source(
1480a2b8659dSTony Cheng 				&context->res_ctx, pool,
14814562236bSHarry Wentland 				pipe_ctx->clock_source);
14824562236bSHarry Wentland 
1483a2b8659dSTony Cheng 			set_audio_in_use(&context->res_ctx, pool,
14844562236bSHarry Wentland 					pipe_ctx->audio);
14854562236bSHarry Wentland 		}
14864562236bSHarry Wentland 	}
14874562236bSHarry Wentland 
1488ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
14890971c40eSHarry Wentland 		struct dc_stream_state *stream = context->streams[i];
14904562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx = NULL;
14914562236bSHarry Wentland 		int pipe_idx = -1;
14924562236bSHarry Wentland 
1493430ef426SDmytro Laktyushkin 		if (old_context && resource_is_stream_unchanged(old_context, stream))
14944562236bSHarry Wentland 			continue;
14954562236bSHarry Wentland 		/* acquire new resources */
14965d11e9fcSDmytro Laktyushkin 		pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
14975d11e9fcSDmytro Laktyushkin #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
14985d11e9fcSDmytro Laktyushkin 		if (pipe_idx < 0)
14995d11e9fcSDmytro Laktyushkin 			acquire_first_split_pipe(&context->res_ctx, pool, stream);
15005d11e9fcSDmytro Laktyushkin #endif
15014562236bSHarry Wentland 		if (pipe_idx < 0)
15024562236bSHarry Wentland 			return DC_NO_CONTROLLER_RESOURCE;
15034562236bSHarry Wentland 
15044562236bSHarry Wentland 		pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
15054562236bSHarry Wentland 
15068e9c4c8cSHarry Wentland 		pipe_ctx->stream_res.stream_enc =
15074562236bSHarry Wentland 			find_first_free_match_stream_enc_for_link(
1508a2b8659dSTony Cheng 				&context->res_ctx, pool, stream);
15094562236bSHarry Wentland 
15108e9c4c8cSHarry Wentland 		if (!pipe_ctx->stream_res.stream_enc)
15114562236bSHarry Wentland 			return DC_NO_STREAM_ENG_RESOURCE;
15124562236bSHarry Wentland 
15134562236bSHarry Wentland 		set_stream_engine_in_use(
1514a2b8659dSTony Cheng 			&context->res_ctx, pool,
15158e9c4c8cSHarry Wentland 			pipe_ctx->stream_res.stream_enc);
15164562236bSHarry Wentland 
15174562236bSHarry Wentland 		/* TODO: Add check if ASIC support and EDID audio */
1518b73a22d3SHarry Wentland 		if (!stream->sink->converter_disable_audio &&
15194562236bSHarry Wentland 			dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
15204fa086b9SLeo (Sunpeng) Li 			stream->audio_info.mode_count) {
15214562236bSHarry Wentland 			pipe_ctx->audio = find_first_free_audio(
1522a2b8659dSTony Cheng 				&context->res_ctx, pool);
15234562236bSHarry Wentland 
15244562236bSHarry Wentland 			/*
15254562236bSHarry Wentland 			 * Audio assigned in order first come first get.
15264562236bSHarry Wentland 			 * There are asics which has number of audio
15274562236bSHarry Wentland 			 * resources less then number of pipes
15284562236bSHarry Wentland 			 */
15294562236bSHarry Wentland 			if (pipe_ctx->audio)
15304562236bSHarry Wentland 				set_audio_in_use(
1531a2b8659dSTony Cheng 					&context->res_ctx, pool,
15324562236bSHarry Wentland 					pipe_ctx->audio);
15334562236bSHarry Wentland 		}
15344562236bSHarry Wentland 
15356b670fa9SHarry Wentland 		context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
15364562236bSHarry Wentland 	}
15374562236bSHarry Wentland 
15384562236bSHarry Wentland 	return DC_OK;
15394562236bSHarry Wentland }
15404562236bSHarry Wentland 
1541ab2541b6SAric Cyr /* first stream in the context is used to populate the rest */
1542ab2541b6SAric Cyr void validate_guaranteed_copy_streams(
15434562236bSHarry Wentland 		struct validate_context *context,
1544ab2541b6SAric Cyr 		int max_streams)
15454562236bSHarry Wentland {
15464562236bSHarry Wentland 	int i;
15474562236bSHarry Wentland 
1548ab2541b6SAric Cyr 	for (i = 1; i < max_streams; i++) {
1549ab2541b6SAric Cyr 		context->streams[i] = context->streams[0];
15504562236bSHarry Wentland 
15514562236bSHarry Wentland 		copy_pipe_ctx(&context->res_ctx.pipe_ctx[0],
15524562236bSHarry Wentland 			      &context->res_ctx.pipe_ctx[i]);
15534562236bSHarry Wentland 		context->res_ctx.pipe_ctx[i].stream =
15544562236bSHarry Wentland 				context->res_ctx.pipe_ctx[0].stream;
15554562236bSHarry Wentland 
15564fa086b9SLeo (Sunpeng) Li 		dc_stream_retain(context->streams[i]);
1557ab2541b6SAric Cyr 		context->stream_count++;
15584562236bSHarry Wentland 	}
15594562236bSHarry Wentland }
15604562236bSHarry Wentland 
15616e4d6beeSTony Cheng static void patch_gamut_packet_checksum(
15626e4d6beeSTony Cheng 		struct encoder_info_packet *gamut_packet)
15634562236bSHarry Wentland {
15644562236bSHarry Wentland 	/* For gamut we recalc checksum */
15656e4d6beeSTony Cheng 	if (gamut_packet->valid) {
15664562236bSHarry Wentland 		uint8_t chk_sum = 0;
15674562236bSHarry Wentland 		uint8_t *ptr;
15684562236bSHarry Wentland 		uint8_t i;
15694562236bSHarry Wentland 
15704562236bSHarry Wentland 		/*start of the Gamut data. */
15716e4d6beeSTony Cheng 		ptr = &gamut_packet->sb[3];
15724562236bSHarry Wentland 
15736e4d6beeSTony Cheng 		for (i = 0; i <= gamut_packet->sb[1]; i++)
15744562236bSHarry Wentland 			chk_sum += ptr[i];
15754562236bSHarry Wentland 
15766e4d6beeSTony Cheng 		gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
15771646a6feSAndrew Wong 	}
15784562236bSHarry Wentland }
15794562236bSHarry Wentland 
15804562236bSHarry Wentland static void set_avi_info_frame(
15816e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
15824562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
15834562236bSHarry Wentland {
15840971c40eSHarry Wentland 	struct dc_stream_state *stream = pipe_ctx->stream;
15854562236bSHarry Wentland 	enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
15864562236bSHarry Wentland 	struct info_frame info_frame = { {0} };
15874562236bSHarry Wentland 	uint32_t pixel_encoding = 0;
15884562236bSHarry Wentland 	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
15894562236bSHarry Wentland 	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
15904562236bSHarry Wentland 	bool itc = false;
159150e27654SZeyu Fan 	uint8_t itc_value = 0;
15924562236bSHarry Wentland 	uint8_t cn0_cn1 = 0;
159350e27654SZeyu Fan 	unsigned int cn0_cn1_value = 0;
15944562236bSHarry Wentland 	uint8_t *check_sum = NULL;
15954562236bSHarry Wentland 	uint8_t byte_index = 0;
1596e8d726b7SReza Amini 	union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi;
159750e27654SZeyu Fan 	union display_content_support support = {0};
15984fa086b9SLeo (Sunpeng) Li 	unsigned int vic = pipe_ctx->stream->timing.vic;
159915e17335SCharlene Liu 	enum dc_timing_3d_format format;
16004562236bSHarry Wentland 
16014fa086b9SLeo (Sunpeng) Li 	color_space = pipe_ctx->stream->output_color_space;
1602e5f2038eSCharlene Liu 	if (color_space == COLOR_SPACE_UNKNOWN)
16034fa086b9SLeo (Sunpeng) Li 		color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ?
1604e5f2038eSCharlene Liu 			COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709;
16054562236bSHarry Wentland 
16064562236bSHarry Wentland 	/* Initialize header */
1607e8d726b7SReza Amini 	hdmi_info->bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
16084562236bSHarry Wentland 	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
16094562236bSHarry Wentland 	* not be used in HDMI 2.0 (Section 10.1) */
1610e8d726b7SReza Amini 	hdmi_info->bits.header.version = 2;
1611e8d726b7SReza Amini 	hdmi_info->bits.header.length = HDMI_AVI_INFOFRAME_SIZE;
16124562236bSHarry Wentland 
16134562236bSHarry Wentland 	/*
16144562236bSHarry Wentland 	 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
16154562236bSHarry Wentland 	 * according to HDMI 2.0 spec (Section 10.1)
16164562236bSHarry Wentland 	 */
16174562236bSHarry Wentland 
16184fa086b9SLeo (Sunpeng) Li 	switch (stream->timing.pixel_encoding) {
16194562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR422:
16204562236bSHarry Wentland 		pixel_encoding = 1;
16214562236bSHarry Wentland 		break;
16224562236bSHarry Wentland 
16234562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR444:
16244562236bSHarry Wentland 		pixel_encoding = 2;
16254562236bSHarry Wentland 		break;
16264562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR420:
16274562236bSHarry Wentland 		pixel_encoding = 3;
16284562236bSHarry Wentland 		break;
16294562236bSHarry Wentland 
16304562236bSHarry Wentland 	case PIXEL_ENCODING_RGB:
16314562236bSHarry Wentland 	default:
16324562236bSHarry Wentland 		pixel_encoding = 0;
16334562236bSHarry Wentland 	}
16344562236bSHarry Wentland 
16354562236bSHarry Wentland 	/* Y0_Y1_Y2 : The pixel encoding */
16364562236bSHarry Wentland 	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
1637e8d726b7SReza Amini 	hdmi_info->bits.Y0_Y1_Y2 = pixel_encoding;
16384562236bSHarry Wentland 
16394562236bSHarry Wentland 	/* A0 = 1 Active Format Information valid */
1640e8d726b7SReza Amini 	hdmi_info->bits.A0 = ACTIVE_FORMAT_VALID;
16414562236bSHarry Wentland 
16424562236bSHarry Wentland 	/* B0, B1 = 3; Bar info data is valid */
1643e8d726b7SReza Amini 	hdmi_info->bits.B0_B1 = BAR_INFO_BOTH_VALID;
16444562236bSHarry Wentland 
1645e8d726b7SReza Amini 	hdmi_info->bits.SC0_SC1 = PICTURE_SCALING_UNIFORM;
16464562236bSHarry Wentland 
16474562236bSHarry Wentland 	/* S0, S1 : Underscan / Overscan */
16484562236bSHarry Wentland 	/* TODO: un-hardcode scan type */
16494562236bSHarry Wentland 	scan_type = SCANNING_TYPE_UNDERSCAN;
1650e8d726b7SReza Amini 	hdmi_info->bits.S0_S1 = scan_type;
16514562236bSHarry Wentland 
16524562236bSHarry Wentland 	/* C0, C1 : Colorimetry */
16538fde5884SCharlene Liu 	if (color_space == COLOR_SPACE_YCBCR709 ||
165415e17335SCharlene Liu 			color_space == COLOR_SPACE_YCBCR709_LIMITED)
1655e8d726b7SReza Amini 		hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709;
16568fde5884SCharlene Liu 	else if (color_space == COLOR_SPACE_YCBCR601 ||
16578fde5884SCharlene Liu 			color_space == COLOR_SPACE_YCBCR601_LIMITED)
1658e8d726b7SReza Amini 		hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601;
16598fde5884SCharlene Liu 	else {
1660e8d726b7SReza Amini 		hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA;
16618fde5884SCharlene Liu 	}
1662534db198SAmy Zhang 	if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
1663534db198SAmy Zhang 			color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
1664534db198SAmy Zhang 			color_space == COLOR_SPACE_2020_YCBCR) {
1665e8d726b7SReza Amini 		hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
1666e8d726b7SReza Amini 		hdmi_info->bits.C0_C1   = COLORIMETRY_EXTENDED;
1667534db198SAmy Zhang 	} else if (color_space == COLOR_SPACE_ADOBERGB) {
1668e8d726b7SReza Amini 		hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
1669e8d726b7SReza Amini 		hdmi_info->bits.C0_C1   = COLORIMETRY_EXTENDED;
1670534db198SAmy Zhang 	}
1671534db198SAmy Zhang 
16724562236bSHarry Wentland 	/* TODO: un-hardcode aspect ratio */
16734fa086b9SLeo (Sunpeng) Li 	aspect = stream->timing.aspect_ratio;
16744562236bSHarry Wentland 
16754562236bSHarry Wentland 	switch (aspect) {
16764562236bSHarry Wentland 	case ASPECT_RATIO_4_3:
16774562236bSHarry Wentland 	case ASPECT_RATIO_16_9:
1678e8d726b7SReza Amini 		hdmi_info->bits.M0_M1 = aspect;
16794562236bSHarry Wentland 		break;
16804562236bSHarry Wentland 
16814562236bSHarry Wentland 	case ASPECT_RATIO_NO_DATA:
16824562236bSHarry Wentland 	case ASPECT_RATIO_64_27:
16834562236bSHarry Wentland 	case ASPECT_RATIO_256_135:
16844562236bSHarry Wentland 	default:
1685e8d726b7SReza Amini 		hdmi_info->bits.M0_M1 = 0;
16864562236bSHarry Wentland 	}
16874562236bSHarry Wentland 
16884562236bSHarry Wentland 	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
1689e8d726b7SReza Amini 	hdmi_info->bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
16904562236bSHarry Wentland 
16914562236bSHarry Wentland 	/* TODO: un-hardcode cn0_cn1 and itc */
169250e27654SZeyu Fan 
16934562236bSHarry Wentland 	cn0_cn1 = 0;
169450e27654SZeyu Fan 	cn0_cn1_value = 0;
169550e27654SZeyu Fan 
169650e27654SZeyu Fan 	itc = true;
169750e27654SZeyu Fan 	itc_value = 1;
169850e27654SZeyu Fan 
16994fa086b9SLeo (Sunpeng) Li 	support = stream->sink->edid_caps.content_support;
17004562236bSHarry Wentland 
17014562236bSHarry Wentland 	if (itc) {
170250e27654SZeyu Fan 		if (!support.bits.valid_content_type) {
170350e27654SZeyu Fan 			cn0_cn1_value = 0;
170450e27654SZeyu Fan 		} else {
170550e27654SZeyu Fan 			if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) {
170650e27654SZeyu Fan 				if (support.bits.graphics_content == 1) {
170750e27654SZeyu Fan 					cn0_cn1_value = 0;
170850e27654SZeyu Fan 				}
170950e27654SZeyu Fan 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) {
171050e27654SZeyu Fan 				if (support.bits.photo_content == 1) {
171150e27654SZeyu Fan 					cn0_cn1_value = 1;
171250e27654SZeyu Fan 				} else {
171350e27654SZeyu Fan 					cn0_cn1_value = 0;
171450e27654SZeyu Fan 					itc_value = 0;
171550e27654SZeyu Fan 				}
171650e27654SZeyu Fan 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) {
171750e27654SZeyu Fan 				if (support.bits.cinema_content == 1) {
171850e27654SZeyu Fan 					cn0_cn1_value = 2;
171950e27654SZeyu Fan 				} else {
172050e27654SZeyu Fan 					cn0_cn1_value = 0;
172150e27654SZeyu Fan 					itc_value = 0;
172250e27654SZeyu Fan 				}
172350e27654SZeyu Fan 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) {
172450e27654SZeyu Fan 				if (support.bits.game_content == 1) {
172550e27654SZeyu Fan 					cn0_cn1_value = 3;
172650e27654SZeyu Fan 				} else {
172750e27654SZeyu Fan 					cn0_cn1_value = 0;
172850e27654SZeyu Fan 					itc_value = 0;
172950e27654SZeyu Fan 				}
173050e27654SZeyu Fan 			}
173150e27654SZeyu Fan 		}
173250e27654SZeyu Fan 		hdmi_info->bits.CN0_CN1 = cn0_cn1_value;
173350e27654SZeyu Fan 		hdmi_info->bits.ITC = itc_value;
17344562236bSHarry Wentland 	}
17354562236bSHarry Wentland 
17364562236bSHarry Wentland 	/* TODO : We should handle YCC quantization */
17374562236bSHarry Wentland 	/* but we do not have matrix calculation */
17384fa086b9SLeo (Sunpeng) Li 	if (stream->sink->edid_caps.qs_bit == 1 &&
17394fa086b9SLeo (Sunpeng) Li 			stream->sink->edid_caps.qy_bit == 1) {
174050e27654SZeyu Fan 		if (color_space == COLOR_SPACE_SRGB ||
174150e27654SZeyu Fan 			color_space == COLOR_SPACE_2020_RGB_FULLRANGE) {
1742e8d726b7SReza Amini 			hdmi_info->bits.Q0_Q1   = RGB_QUANTIZATION_FULL_RANGE;
1743e8d726b7SReza Amini 			hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE;
174450e27654SZeyu Fan 		} else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
174550e27654SZeyu Fan 					color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) {
1746e8d726b7SReza Amini 			hdmi_info->bits.Q0_Q1   = RGB_QUANTIZATION_LIMITED_RANGE;
1747e8d726b7SReza Amini 			hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
17484562236bSHarry Wentland 		} else {
1749e8d726b7SReza Amini 			hdmi_info->bits.Q0_Q1   = RGB_QUANTIZATION_DEFAULT_RANGE;
1750e8d726b7SReza Amini 			hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
17514562236bSHarry Wentland 		}
175250e27654SZeyu Fan 	} else {
175350e27654SZeyu Fan 		hdmi_info->bits.Q0_Q1   = RGB_QUANTIZATION_DEFAULT_RANGE;
175450e27654SZeyu Fan 		hdmi_info->bits.YQ0_YQ1   = YYC_QUANTIZATION_LIMITED_RANGE;
175550e27654SZeyu Fan 	}
175650e27654SZeyu Fan 
175715e17335SCharlene Liu 	///VIC
17584fa086b9SLeo (Sunpeng) Li 	format = stream->timing.timing_3d_format;
175915e17335SCharlene Liu 	/*todo, add 3DStereo support*/
176015e17335SCharlene Liu 	if (format != TIMING_3D_FORMAT_NONE) {
176115e17335SCharlene Liu 		// Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled
17624fa086b9SLeo (Sunpeng) Li 		switch (pipe_ctx->stream->timing.hdmi_vic) {
176315e17335SCharlene Liu 		case 1:
176415e17335SCharlene Liu 			vic = 95;
176515e17335SCharlene Liu 			break;
176615e17335SCharlene Liu 		case 2:
176715e17335SCharlene Liu 			vic = 94;
176815e17335SCharlene Liu 			break;
176915e17335SCharlene Liu 		case 3:
177015e17335SCharlene Liu 			vic = 93;
177115e17335SCharlene Liu 			break;
177215e17335SCharlene Liu 		case 4:
177315e17335SCharlene Liu 			vic = 98;
177415e17335SCharlene Liu 			break;
177515e17335SCharlene Liu 		default:
177615e17335SCharlene Liu 			break;
177715e17335SCharlene Liu 		}
177815e17335SCharlene Liu 	}
177915e17335SCharlene Liu 	hdmi_info->bits.VIC0_VIC7 = vic;
17804562236bSHarry Wentland 
17814562236bSHarry Wentland 	/* pixel repetition
17824562236bSHarry Wentland 	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
17834562236bSHarry Wentland 	 * repetition start from 1 */
1784e8d726b7SReza Amini 	hdmi_info->bits.PR0_PR3 = 0;
17854562236bSHarry Wentland 
17864562236bSHarry Wentland 	/* Bar Info
17874562236bSHarry Wentland 	 * barTop:    Line Number of End of Top Bar.
17884562236bSHarry Wentland 	 * barBottom: Line Number of Start of Bottom Bar.
17894562236bSHarry Wentland 	 * barLeft:   Pixel Number of End of Left Bar.
17904562236bSHarry Wentland 	 * barRight:  Pixel Number of Start of Right Bar. */
17914fa086b9SLeo (Sunpeng) Li 	hdmi_info->bits.bar_top = stream->timing.v_border_top;
17924fa086b9SLeo (Sunpeng) Li 	hdmi_info->bits.bar_bottom = (stream->timing.v_total
17934fa086b9SLeo (Sunpeng) Li 			- stream->timing.v_border_bottom + 1);
17944fa086b9SLeo (Sunpeng) Li 	hdmi_info->bits.bar_left  = stream->timing.h_border_left;
17954fa086b9SLeo (Sunpeng) Li 	hdmi_info->bits.bar_right = (stream->timing.h_total
17964fa086b9SLeo (Sunpeng) Li 			- stream->timing.h_border_right + 1);
17974562236bSHarry Wentland 
17984562236bSHarry Wentland 	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
1799e8d726b7SReza Amini 	check_sum = &info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
1800e8d726b7SReza Amini 
18013e183c5fSDave Airlie 	*check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2;
18024562236bSHarry Wentland 
18033e183c5fSDave Airlie 	for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++)
1804e8d726b7SReza Amini 		*check_sum += hdmi_info->packet_raw_data.sb[byte_index];
18054562236bSHarry Wentland 
18064562236bSHarry Wentland 	/* one byte complement */
18074562236bSHarry Wentland 	*check_sum = (uint8_t) (0x100 - *check_sum);
18084562236bSHarry Wentland 
18094562236bSHarry Wentland 	/* Store in hw_path_mode */
1810e8d726b7SReza Amini 	info_packet->hb0 = hdmi_info->packet_raw_data.hb0;
1811e8d726b7SReza Amini 	info_packet->hb1 = hdmi_info->packet_raw_data.hb1;
1812e8d726b7SReza Amini 	info_packet->hb2 = hdmi_info->packet_raw_data.hb2;
18134562236bSHarry Wentland 
1814e66e4d64SHarry Wentland 	for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet.
1815e66e4d64SHarry Wentland 				info_packet_hdmi.packet_raw_data.sb); byte_index++)
18164562236bSHarry Wentland 		info_packet->sb[byte_index] = info_frame.avi_info_packet.
18174562236bSHarry Wentland 				info_packet_hdmi.packet_raw_data.sb[byte_index];
18184562236bSHarry Wentland 
18194562236bSHarry Wentland 	info_packet->valid = true;
18204562236bSHarry Wentland }
18214562236bSHarry Wentland 
18226e4d6beeSTony Cheng static void set_vendor_info_packet(
18236e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
18240971c40eSHarry Wentland 		struct dc_stream_state *stream)
18254562236bSHarry Wentland {
18264562236bSHarry Wentland 	uint32_t length = 0;
18274562236bSHarry Wentland 	bool hdmi_vic_mode = false;
18284562236bSHarry Wentland 	uint8_t checksum = 0;
18294562236bSHarry Wentland 	uint32_t i = 0;
18304562236bSHarry Wentland 	enum dc_timing_3d_format format;
183115e17335SCharlene Liu 	// Can be different depending on packet content /*todo*/
183215e17335SCharlene Liu 	// unsigned int length = pPathMode->dolbyVision ? 24 : 5;
183315e17335SCharlene Liu 
183415e17335SCharlene Liu 	info_packet->valid = false;
18354562236bSHarry Wentland 
18364fa086b9SLeo (Sunpeng) Li 	format = stream->timing.timing_3d_format;
18374fa086b9SLeo (Sunpeng) Li 	if (stream->view_format == VIEW_3D_FORMAT_NONE)
18387f5c22d1SVitaly Prosyak 		format = TIMING_3D_FORMAT_NONE;
18394562236bSHarry Wentland 
18404562236bSHarry Wentland 	/* Can be different depending on packet content */
18414562236bSHarry Wentland 	length = 5;
18424562236bSHarry Wentland 
18434fa086b9SLeo (Sunpeng) Li 	if (stream->timing.hdmi_vic != 0
18444fa086b9SLeo (Sunpeng) Li 			&& stream->timing.h_total >= 3840
18454fa086b9SLeo (Sunpeng) Li 			&& stream->timing.v_total >= 2160)
18464562236bSHarry Wentland 		hdmi_vic_mode = true;
18474562236bSHarry Wentland 
18484562236bSHarry Wentland 	/* According to HDMI 1.4a CTS, VSIF should be sent
18494562236bSHarry Wentland 	 * for both 3D stereo and HDMI VIC modes.
18504562236bSHarry Wentland 	 * For all other modes, there is no VSIF sent.  */
18514562236bSHarry Wentland 
18524562236bSHarry Wentland 	if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
18534562236bSHarry Wentland 		return;
18544562236bSHarry Wentland 
18554562236bSHarry Wentland 	/* 24bit IEEE Registration identifier (0x000c03). LSB first. */
18564562236bSHarry Wentland 	info_packet->sb[1] = 0x03;
18574562236bSHarry Wentland 	info_packet->sb[2] = 0x0C;
18584562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
18594562236bSHarry Wentland 
18604562236bSHarry Wentland 	/*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
18614562236bSHarry Wentland 	 * The value for HDMI_Video_Format are:
18624562236bSHarry Wentland 	 * 0x0 (0b000) - No additional HDMI video format is presented in this
18634562236bSHarry Wentland 	 * packet
18644562236bSHarry Wentland 	 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
18654562236bSHarry Wentland 	 * parameter follows
18664562236bSHarry Wentland 	 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
18674562236bSHarry Wentland 	 * potentially 3D_Ext_Data follows
18684562236bSHarry Wentland 	 * 0x3..0x7 (0b011..0b111) - reserved for future use */
18694562236bSHarry Wentland 	if (format != TIMING_3D_FORMAT_NONE)
18704562236bSHarry Wentland 		info_packet->sb[4] = (2 << 5);
18714562236bSHarry Wentland 	else if (hdmi_vic_mode)
18724562236bSHarry Wentland 		info_packet->sb[4] = (1 << 5);
18734562236bSHarry Wentland 
18744562236bSHarry Wentland 	/* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
18754562236bSHarry Wentland 	 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
18764562236bSHarry Wentland 	 * The value for 3D_Structure are:
18774562236bSHarry Wentland 	 * 0x0 - Frame Packing
18784562236bSHarry Wentland 	 * 0x1 - Field Alternative
18794562236bSHarry Wentland 	 * 0x2 - Line Alternative
18804562236bSHarry Wentland 	 * 0x3 - Side-by-Side (full)
18814562236bSHarry Wentland 	 * 0x4 - L + depth
18824562236bSHarry Wentland 	 * 0x5 - L + depth + graphics + graphics-depth
18834562236bSHarry Wentland 	 * 0x6 - Top-and-Bottom
18844562236bSHarry Wentland 	 * 0x7 - Reserved for future use
18854562236bSHarry Wentland 	 * 0x8 - Side-by-Side (Half)
18864562236bSHarry Wentland 	 * 0x9..0xE - Reserved for future use
18874562236bSHarry Wentland 	 * 0xF - Not used */
18884562236bSHarry Wentland 	switch (format) {
18894562236bSHarry Wentland 	case TIMING_3D_FORMAT_HW_FRAME_PACKING:
18904562236bSHarry Wentland 	case TIMING_3D_FORMAT_SW_FRAME_PACKING:
18914562236bSHarry Wentland 		info_packet->sb[5] = (0x0 << 4);
18924562236bSHarry Wentland 		break;
18934562236bSHarry Wentland 
18944562236bSHarry Wentland 	case TIMING_3D_FORMAT_SIDE_BY_SIDE:
18954562236bSHarry Wentland 	case TIMING_3D_FORMAT_SBS_SW_PACKED:
18964562236bSHarry Wentland 		info_packet->sb[5] = (0x8 << 4);
18974562236bSHarry Wentland 		length = 6;
18984562236bSHarry Wentland 		break;
18994562236bSHarry Wentland 
19004562236bSHarry Wentland 	case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
19014562236bSHarry Wentland 	case TIMING_3D_FORMAT_TB_SW_PACKED:
19024562236bSHarry Wentland 		info_packet->sb[5] = (0x6 << 4);
19034562236bSHarry Wentland 		break;
19044562236bSHarry Wentland 
19054562236bSHarry Wentland 	default:
19064562236bSHarry Wentland 		break;
19074562236bSHarry Wentland 	}
19084562236bSHarry Wentland 
19094562236bSHarry Wentland 	/*PB5: If PB4 is set to 0x1 (extended resolution format)
19104562236bSHarry Wentland 	 * fill PB5 with the correct HDMI VIC code */
19114562236bSHarry Wentland 	if (hdmi_vic_mode)
19124fa086b9SLeo (Sunpeng) Li 		info_packet->sb[5] = stream->timing.hdmi_vic;
19134562236bSHarry Wentland 
19144562236bSHarry Wentland 	/* Header */
19153e183c5fSDave Airlie 	info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */
19164562236bSHarry Wentland 	info_packet->hb1 = 0x01; /* Version */
19174562236bSHarry Wentland 
19184562236bSHarry Wentland 	/* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
19194562236bSHarry Wentland 	info_packet->hb2 = (uint8_t) (length);
19204562236bSHarry Wentland 
19214562236bSHarry Wentland 	/* Calculate checksum */
19224562236bSHarry Wentland 	checksum = 0;
19234562236bSHarry Wentland 	checksum += info_packet->hb0;
19244562236bSHarry Wentland 	checksum += info_packet->hb1;
19254562236bSHarry Wentland 	checksum += info_packet->hb2;
19264562236bSHarry Wentland 
19274562236bSHarry Wentland 	for (i = 1; i <= length; i++)
19284562236bSHarry Wentland 		checksum += info_packet->sb[i];
19294562236bSHarry Wentland 
19304562236bSHarry Wentland 	info_packet->sb[0] = (uint8_t) (0x100 - checksum);
19314562236bSHarry Wentland 
19324562236bSHarry Wentland 	info_packet->valid = true;
19334562236bSHarry Wentland }
19344562236bSHarry Wentland 
19356e4d6beeSTony Cheng static void set_spd_info_packet(
19366e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
19370971c40eSHarry Wentland 		struct dc_stream_state *stream)
19384562236bSHarry Wentland {
19394562236bSHarry Wentland 	/* SPD info packet for FreeSync */
19404562236bSHarry Wentland 
19414562236bSHarry Wentland 	unsigned char checksum = 0;
19424562236bSHarry Wentland 	unsigned int idx, payload_size = 0;
19434562236bSHarry Wentland 
19444562236bSHarry Wentland 	/* Check if Freesync is supported. Return if false. If true,
19454562236bSHarry Wentland 	 * set the corresponding bit in the info packet
19464562236bSHarry Wentland 	 */
19474fa086b9SLeo (Sunpeng) Li 	if (stream->freesync_ctx.supported == false)
19484562236bSHarry Wentland 		return;
19494562236bSHarry Wentland 
19504562236bSHarry Wentland 	if (dc_is_hdmi_signal(stream->signal)) {
19514562236bSHarry Wentland 
19524562236bSHarry Wentland 		/* HEADER */
19534562236bSHarry Wentland 
19544562236bSHarry Wentland 		/* HB0  = Packet Type = 0x83 (Source Product
19554562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
19564562236bSHarry Wentland 		 */
19573e183c5fSDave Airlie 		info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD;
19584562236bSHarry Wentland 
19594562236bSHarry Wentland 		/* HB1  = Version = 0x01 */
19604562236bSHarry Wentland 		info_packet->hb1 = 0x01;
19614562236bSHarry Wentland 
19624562236bSHarry Wentland 		/* HB2  = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
19634562236bSHarry Wentland 		info_packet->hb2 = 0x08;
19644562236bSHarry Wentland 
19654562236bSHarry Wentland 		payload_size = 0x08;
19664562236bSHarry Wentland 
19674562236bSHarry Wentland 	} else if (dc_is_dp_signal(stream->signal)) {
19684562236bSHarry Wentland 
19694562236bSHarry Wentland 		/* HEADER */
19704562236bSHarry Wentland 
19714562236bSHarry Wentland 		/* HB0  = Secondary-data Packet ID = 0 - Only non-zero
19724562236bSHarry Wentland 		 *	  when used to associate audio related info packets
19734562236bSHarry Wentland 		 */
19744562236bSHarry Wentland 		info_packet->hb0 = 0x00;
19754562236bSHarry Wentland 
19764562236bSHarry Wentland 		/* HB1  = Packet Type = 0x83 (Source Product
19774562236bSHarry Wentland 		 *	  Descriptor InfoFrame)
19784562236bSHarry Wentland 		 */
19793e183c5fSDave Airlie 		info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD;
19804562236bSHarry Wentland 
19814562236bSHarry Wentland 		/* HB2  = [Bits 7:0 = Least significant eight bits -
19824562236bSHarry Wentland 		 *	  For INFOFRAME, the value must be 1Bh]
19834562236bSHarry Wentland 		 */
19844562236bSHarry Wentland 		info_packet->hb2 = 0x1B;
19854562236bSHarry Wentland 
19864562236bSHarry Wentland 		/* HB3  = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
19874562236bSHarry Wentland 		 *	  [Bits 1:0 = Most significant two bits = 0x00]
19884562236bSHarry Wentland 		 */
19894562236bSHarry Wentland 		info_packet->hb3 = 0x04;
19904562236bSHarry Wentland 
19914562236bSHarry Wentland 		payload_size = 0x1B;
19924562236bSHarry Wentland 	}
19934562236bSHarry Wentland 
19944562236bSHarry Wentland 	/* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
19954562236bSHarry Wentland 	info_packet->sb[1] = 0x1A;
19964562236bSHarry Wentland 
19974562236bSHarry Wentland 	/* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
19984562236bSHarry Wentland 	info_packet->sb[2] = 0x00;
19994562236bSHarry Wentland 
20004562236bSHarry Wentland 	/* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
20014562236bSHarry Wentland 	info_packet->sb[3] = 0x00;
20024562236bSHarry Wentland 
20034562236bSHarry Wentland 	/* PB4 = Reserved */
20044562236bSHarry Wentland 	info_packet->sb[4] = 0x00;
20054562236bSHarry Wentland 
20064562236bSHarry Wentland 	/* PB5 = Reserved */
20074562236bSHarry Wentland 	info_packet->sb[5] = 0x00;
20084562236bSHarry Wentland 
20094562236bSHarry Wentland 	/* PB6 = [Bits 7:3 = Reserved] */
20104562236bSHarry Wentland 	info_packet->sb[6] = 0x00;
20114562236bSHarry Wentland 
20124fa086b9SLeo (Sunpeng) Li 	if (stream->freesync_ctx.supported == true)
20134562236bSHarry Wentland 		/* PB6 = [Bit 0 = FreeSync Supported] */
20144562236bSHarry Wentland 		info_packet->sb[6] |= 0x01;
20154562236bSHarry Wentland 
20164fa086b9SLeo (Sunpeng) Li 	if (stream->freesync_ctx.enabled == true)
20174562236bSHarry Wentland 		/* PB6 = [Bit 1 = FreeSync Enabled] */
20184562236bSHarry Wentland 		info_packet->sb[6] |= 0x02;
20194562236bSHarry Wentland 
20204fa086b9SLeo (Sunpeng) Li 	if (stream->freesync_ctx.active == true)
20214562236bSHarry Wentland 		/* PB6 = [Bit 2 = FreeSync Active] */
20224562236bSHarry Wentland 		info_packet->sb[6] |= 0x04;
20234562236bSHarry Wentland 
20244562236bSHarry Wentland 	/* PB7 = FreeSync Minimum refresh rate (Hz) */
20254fa086b9SLeo (Sunpeng) Li 	info_packet->sb[7] = (unsigned char) (stream->freesync_ctx.
20264562236bSHarry Wentland 			min_refresh_in_micro_hz / 1000000);
20274562236bSHarry Wentland 
20284562236bSHarry Wentland 	/* PB8 = FreeSync Maximum refresh rate (Hz)
20294562236bSHarry Wentland 	 *
20304562236bSHarry Wentland 	 * Note: We do not use the maximum capable refresh rate
20314562236bSHarry Wentland 	 * of the panel, because we should never go above the field
20324562236bSHarry Wentland 	 * rate of the mode timing set.
20334562236bSHarry Wentland 	 */
20344fa086b9SLeo (Sunpeng) Li 	info_packet->sb[8] = (unsigned char) (stream->freesync_ctx.
20354562236bSHarry Wentland 			nominal_refresh_in_micro_hz / 1000000);
20364562236bSHarry Wentland 
20374562236bSHarry Wentland 	/* PB9 - PB27  = Reserved */
20384562236bSHarry Wentland 	for (idx = 9; idx <= 27; idx++)
20394562236bSHarry Wentland 		info_packet->sb[idx] = 0x00;
20404562236bSHarry Wentland 
20414562236bSHarry Wentland 	/* Calculate checksum */
20424562236bSHarry Wentland 	checksum += info_packet->hb0;
20434562236bSHarry Wentland 	checksum += info_packet->hb1;
20444562236bSHarry Wentland 	checksum += info_packet->hb2;
20454562236bSHarry Wentland 	checksum += info_packet->hb3;
20464562236bSHarry Wentland 
20474562236bSHarry Wentland 	for (idx = 1; idx <= payload_size; idx++)
20484562236bSHarry Wentland 		checksum += info_packet->sb[idx];
20494562236bSHarry Wentland 
20504562236bSHarry Wentland 	/* PB0 = Checksum (one byte complement) */
20514562236bSHarry Wentland 	info_packet->sb[0] = (unsigned char) (0x100 - checksum);
20524562236bSHarry Wentland 
20534562236bSHarry Wentland 	info_packet->valid = true;
20544562236bSHarry Wentland }
20554562236bSHarry Wentland 
20561646a6feSAndrew Wong static void set_hdr_static_info_packet(
20576e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
20583be5262eSHarry Wentland 		struct dc_plane_state *plane_state,
20590971c40eSHarry Wentland 		struct dc_stream_state *stream)
20601646a6feSAndrew Wong {
2061e5cf325bSHarry Wentland 	uint16_t i = 0;
20621646a6feSAndrew Wong 	enum signal_type signal = stream->signal;
2063e5cf325bSHarry Wentland 	struct dc_hdr_static_metadata hdr_metadata;
2064e5cf325bSHarry Wentland 	uint32_t data;
20651646a6feSAndrew Wong 
20663be5262eSHarry Wentland 	if (!plane_state)
20671646a6feSAndrew Wong 		return;
20681646a6feSAndrew Wong 
20693be5262eSHarry Wentland 	hdr_metadata = plane_state->hdr_static_ctx;
20701646a6feSAndrew Wong 
207170063a59SAmy Zhang 	if (!hdr_metadata.hdr_supported)
207210bff005SYongqiang Sun 		return;
207310bff005SYongqiang Sun 
20741646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
20751646a6feSAndrew Wong 		info_packet->valid = true;
20761646a6feSAndrew Wong 
20771646a6feSAndrew Wong 		info_packet->hb0 = 0x87;
20781646a6feSAndrew Wong 		info_packet->hb1 = 0x01;
20791646a6feSAndrew Wong 		info_packet->hb2 = 0x1A;
20801646a6feSAndrew Wong 		i = 1;
20811646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
20821646a6feSAndrew Wong 		info_packet->valid = true;
20831646a6feSAndrew Wong 
20841646a6feSAndrew Wong 		info_packet->hb0 = 0x00;
20851646a6feSAndrew Wong 		info_packet->hb1 = 0x87;
20861646a6feSAndrew Wong 		info_packet->hb2 = 0x1D;
20871646a6feSAndrew Wong 		info_packet->hb3 = (0x13 << 2);
20881646a6feSAndrew Wong 		i = 2;
20891646a6feSAndrew Wong 	}
20901646a6feSAndrew Wong 
20911646a6feSAndrew Wong 	data = hdr_metadata.is_hdr;
20921646a6feSAndrew Wong 	info_packet->sb[i++] = data ? 0x02 : 0x00;
20931646a6feSAndrew Wong 	info_packet->sb[i++] = 0x00;
20941646a6feSAndrew Wong 
20951646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_x / 2;
20961646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
20971646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
20981646a6feSAndrew Wong 
20991646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_green_y / 2;
21001646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21011646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21021646a6feSAndrew Wong 
21031646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_x / 2;
21041646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21051646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21061646a6feSAndrew Wong 
21071646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_blue_y / 2;
21081646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21091646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21101646a6feSAndrew Wong 
21111646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_x / 2;
21121646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21131646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21141646a6feSAndrew Wong 
21151646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_red_y / 2;
21161646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21171646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21181646a6feSAndrew Wong 
21191646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_x / 2;
21201646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21211646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21221646a6feSAndrew Wong 
21231646a6feSAndrew Wong 	data = hdr_metadata.chromaticity_white_point_y / 2;
21241646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21251646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21261646a6feSAndrew Wong 
21271646a6feSAndrew Wong 	data = hdr_metadata.max_luminance;
21281646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21291646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21301646a6feSAndrew Wong 
21311646a6feSAndrew Wong 	data = hdr_metadata.min_luminance;
21321646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21331646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21341646a6feSAndrew Wong 
21351646a6feSAndrew Wong 	data = hdr_metadata.maximum_content_light_level;
21361646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21371646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21381646a6feSAndrew Wong 
21391646a6feSAndrew Wong 	data = hdr_metadata.maximum_frame_average_light_level;
21401646a6feSAndrew Wong 	info_packet->sb[i++] = data & 0xFF;
21411646a6feSAndrew Wong 	info_packet->sb[i++] = (data & 0xFF00) >> 8;
21421646a6feSAndrew Wong 
21431646a6feSAndrew Wong 	if (dc_is_hdmi_signal(signal)) {
21441646a6feSAndrew Wong 		uint32_t checksum = 0;
21451646a6feSAndrew Wong 
21461646a6feSAndrew Wong 		checksum += info_packet->hb0;
21471646a6feSAndrew Wong 		checksum += info_packet->hb1;
21481646a6feSAndrew Wong 		checksum += info_packet->hb2;
21491646a6feSAndrew Wong 
21501646a6feSAndrew Wong 		for (i = 1; i <= info_packet->hb2; i++)
21511646a6feSAndrew Wong 			checksum += info_packet->sb[i];
21521646a6feSAndrew Wong 
21531646a6feSAndrew Wong 		info_packet->sb[0] = 0x100 - checksum;
21541646a6feSAndrew Wong 	} else if (dc_is_dp_signal(signal)) {
21551646a6feSAndrew Wong 		info_packet->sb[0] = 0x01;
21561646a6feSAndrew Wong 		info_packet->sb[1] = 0x1A;
21571646a6feSAndrew Wong 	}
21581646a6feSAndrew Wong }
21591646a6feSAndrew Wong 
21606e4d6beeSTony Cheng static void set_vsc_info_packet(
21616e4d6beeSTony Cheng 		struct encoder_info_packet *info_packet,
21620971c40eSHarry Wentland 		struct dc_stream_state *stream)
21634562236bSHarry Wentland {
21644562236bSHarry Wentland 	unsigned int vscPacketRevision = 0;
21654562236bSHarry Wentland 	unsigned int i;
21664562236bSHarry Wentland 
216794267b3dSSylvia Tsai 	if (stream->sink->link->psr_enabled) {
21684562236bSHarry Wentland 		vscPacketRevision = 2;
21694562236bSHarry Wentland 	}
21704562236bSHarry Wentland 
21714562236bSHarry Wentland 	/* VSC packet not needed based on the features
21724562236bSHarry Wentland 	 * supported by this DP display
21734562236bSHarry Wentland 	 */
21744562236bSHarry Wentland 	if (vscPacketRevision == 0)
21754562236bSHarry Wentland 		return;
21764562236bSHarry Wentland 
21774562236bSHarry Wentland 	if (vscPacketRevision == 0x2) {
21784562236bSHarry Wentland 		/* Secondary-data Packet ID = 0*/
21794562236bSHarry Wentland 		info_packet->hb0 = 0x00;
21804562236bSHarry Wentland 		/* 07h - Packet Type Value indicating Video
21814562236bSHarry Wentland 		 * Stream Configuration packet
21824562236bSHarry Wentland 		 */
21834562236bSHarry Wentland 		info_packet->hb1 = 0x07;
21844562236bSHarry Wentland 		/* 02h = VSC SDP supporting 3D stereo and PSR
21854562236bSHarry Wentland 		 * (applies to eDP v1.3 or higher).
21864562236bSHarry Wentland 		 */
21874562236bSHarry Wentland 		info_packet->hb2 = 0x02;
21884562236bSHarry Wentland 		/* 08h = VSC packet supporting 3D stereo + PSR
21894562236bSHarry Wentland 		 * (HB2 = 02h).
21904562236bSHarry Wentland 		 */
21914562236bSHarry Wentland 		info_packet->hb3 = 0x08;
21924562236bSHarry Wentland 
21934562236bSHarry Wentland 		for (i = 0; i < 28; i++)
21944562236bSHarry Wentland 			info_packet->sb[i] = 0;
21954562236bSHarry Wentland 
21964562236bSHarry Wentland 		info_packet->valid = true;
21974562236bSHarry Wentland 	}
21984562236bSHarry Wentland 
21994562236bSHarry Wentland 	/*TODO: stereo 3D support and extend pixel encoding colorimetry*/
22004562236bSHarry Wentland }
22014562236bSHarry Wentland 
22028122a253SHarry Wentland void dc_resource_validate_ctx_destruct(struct validate_context *context)
22034562236bSHarry Wentland {
22044562236bSHarry Wentland 	int i, j;
22054562236bSHarry Wentland 
2206ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
22073be5262eSHarry Wentland 		for (j = 0; j < context->stream_status[i].plane_count; j++)
22083be5262eSHarry Wentland 			dc_plane_state_release(
22093be5262eSHarry Wentland 				context->stream_status[i].plane_states[j]);
22104562236bSHarry Wentland 
22113be5262eSHarry Wentland 		context->stream_status[i].plane_count = 0;
22124fa086b9SLeo (Sunpeng) Li 		dc_stream_release(context->streams[i]);
2213ab2541b6SAric Cyr 		context->streams[i] = NULL;
22144562236bSHarry Wentland 	}
22154562236bSHarry Wentland }
22164562236bSHarry Wentland 
22174562236bSHarry Wentland /*
2218ab2541b6SAric Cyr  * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced
22194562236bSHarry Wentland  * by the src_ctx
22204562236bSHarry Wentland  */
22218122a253SHarry Wentland void dc_resource_validate_ctx_copy_construct(
22224562236bSHarry Wentland 		const struct validate_context *src_ctx,
22234562236bSHarry Wentland 		struct validate_context *dst_ctx)
22244562236bSHarry Wentland {
22254562236bSHarry Wentland 	int i, j;
22269a3afbb3SAndrey Grodzovsky 	int ref_count = dst_ctx->ref_count;
22274562236bSHarry Wentland 
22284562236bSHarry Wentland 	*dst_ctx = *src_ctx;
22294562236bSHarry Wentland 
2230a2b8659dSTony Cheng 	for (i = 0; i < MAX_PIPES; i++) {
22314562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
22324562236bSHarry Wentland 
22334562236bSHarry Wentland 		if (cur_pipe->top_pipe)
22344562236bSHarry Wentland 			cur_pipe->top_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
22354562236bSHarry Wentland 
22364562236bSHarry Wentland 		if (cur_pipe->bottom_pipe)
22374562236bSHarry Wentland 			cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
22384562236bSHarry Wentland 
22394562236bSHarry Wentland 	}
22404562236bSHarry Wentland 
2241ab2541b6SAric Cyr 	for (i = 0; i < dst_ctx->stream_count; i++) {
22424fa086b9SLeo (Sunpeng) Li 		dc_stream_retain(dst_ctx->streams[i]);
22433be5262eSHarry Wentland 		for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++)
22443be5262eSHarry Wentland 			dc_plane_state_retain(
22453be5262eSHarry Wentland 				dst_ctx->stream_status[i].plane_states[j]);
22464562236bSHarry Wentland 	}
22479a3afbb3SAndrey Grodzovsky 
22489a3afbb3SAndrey Grodzovsky 	/* context refcount should not be overridden */
22499a3afbb3SAndrey Grodzovsky 	dst_ctx->ref_count = ref_count;
22509a3afbb3SAndrey Grodzovsky 
22514562236bSHarry Wentland }
22524562236bSHarry Wentland 
22534562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll(
2254a2b8659dSTony Cheng 		struct resource_context *res_ctx,
2255a2b8659dSTony Cheng 		const struct resource_pool *pool)
22564562236bSHarry Wentland {
22574562236bSHarry Wentland 	int i;
22584562236bSHarry Wentland 
2259a2b8659dSTony Cheng 	for (i = 0; i < pool->clk_src_count; ++i) {
22604562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
2261a2b8659dSTony Cheng 			return pool->clock_sources[i];
22624562236bSHarry Wentland 	}
22634562236bSHarry Wentland 
22644562236bSHarry Wentland 	return NULL;
22654562236bSHarry Wentland }
22664562236bSHarry Wentland 
22674562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
22684562236bSHarry Wentland {
22694562236bSHarry Wentland 	enum signal_type signal = SIGNAL_TYPE_NONE;
22706e4d6beeSTony Cheng 	struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame;
22714562236bSHarry Wentland 
22724562236bSHarry Wentland 	/* default all packets to invalid */
22736e4d6beeSTony Cheng 	info->avi.valid = false;
22746e4d6beeSTony Cheng 	info->gamut.valid = false;
22756e4d6beeSTony Cheng 	info->vendor.valid = false;
2276630e3573SJeff Smith 	info->spd.valid = false;
22776e4d6beeSTony Cheng 	info->hdrsmd.valid = false;
22786e4d6beeSTony Cheng 	info->vsc.valid = false;
22794562236bSHarry Wentland 
22804562236bSHarry Wentland 	signal = pipe_ctx->stream->signal;
22814562236bSHarry Wentland 
22824562236bSHarry Wentland 	/* HDMi and DP have different info packets*/
22834562236bSHarry Wentland 	if (dc_is_hdmi_signal(signal)) {
22846e4d6beeSTony Cheng 		set_avi_info_frame(&info->avi, pipe_ctx);
22856e4d6beeSTony Cheng 
22866e4d6beeSTony Cheng 		set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
22876e4d6beeSTony Cheng 
22886e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
22896e4d6beeSTony Cheng 
22906e4d6beeSTony Cheng 		set_hdr_static_info_packet(&info->hdrsmd,
22913be5262eSHarry Wentland 				pipe_ctx->plane_state, pipe_ctx->stream);
22926e4d6beeSTony Cheng 
2293a33fa99dSHarry Wentland 	} else if (dc_is_dp_signal(signal)) {
22946e4d6beeSTony Cheng 		set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
22956e4d6beeSTony Cheng 
22966e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
22976e4d6beeSTony Cheng 
22986e4d6beeSTony Cheng 		set_hdr_static_info_packet(&info->hdrsmd,
22993be5262eSHarry Wentland 				pipe_ctx->plane_state, pipe_ctx->stream);
2300a33fa99dSHarry Wentland 	}
23014562236bSHarry Wentland 
23026e4d6beeSTony Cheng 	patch_gamut_packet_checksum(&info->gamut);
23034562236bSHarry Wentland }
23044562236bSHarry Wentland 
23054562236bSHarry Wentland enum dc_status resource_map_clock_resources(
23064562236bSHarry Wentland 		const struct core_dc *dc,
2307430ef426SDmytro Laktyushkin 		struct validate_context *context,
2308430ef426SDmytro Laktyushkin 		struct validate_context *old_context)
23094562236bSHarry Wentland {
2310ab2541b6SAric Cyr 	int i, j;
2311a2b8659dSTony Cheng 	const struct resource_pool *pool = dc->res_pool;
23124562236bSHarry Wentland 
23134562236bSHarry Wentland 	/* acquire new resources */
2314ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
23150971c40eSHarry Wentland 		struct dc_stream_state *stream = context->streams[i];
23164562236bSHarry Wentland 
2317430ef426SDmytro Laktyushkin 		if (old_context && resource_is_stream_unchanged(old_context, stream))
23184562236bSHarry Wentland 			continue;
23194562236bSHarry Wentland 
2320ab2541b6SAric Cyr 		for (j = 0; j < MAX_PIPES; j++) {
23214562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx =
2322ab2541b6SAric Cyr 				&context->res_ctx.pipe_ctx[j];
23234562236bSHarry Wentland 
2324ab2541b6SAric Cyr 			if (context->res_ctx.pipe_ctx[j].stream != stream)
23254562236bSHarry Wentland 				continue;
23264562236bSHarry Wentland 
23274562236bSHarry Wentland 			if (dc_is_dp_signal(pipe_ctx->stream->signal)
23284562236bSHarry Wentland 				|| pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
2329a2b8659dSTony Cheng 				pipe_ctx->clock_source = pool->dp_clock_source;
23304562236bSHarry Wentland 			else {
23314562236bSHarry Wentland 				pipe_ctx->clock_source = NULL;
23324562236bSHarry Wentland 
23334562236bSHarry Wentland 				if (!dc->public.config.disable_disp_pll_sharing)
23344562236bSHarry Wentland 					resource_find_used_clk_src_for_sharing(
23354562236bSHarry Wentland 						&context->res_ctx,
23364562236bSHarry Wentland 						pipe_ctx);
23374562236bSHarry Wentland 
23384562236bSHarry Wentland 				if (pipe_ctx->clock_source == NULL)
23394562236bSHarry Wentland 					pipe_ctx->clock_source =
2340a2b8659dSTony Cheng 						dc_resource_find_first_free_pll(
2341a2b8659dSTony Cheng 							&context->res_ctx,
2342a2b8659dSTony Cheng 							pool);
23434562236bSHarry Wentland 			}
23444562236bSHarry Wentland 
23454562236bSHarry Wentland 			if (pipe_ctx->clock_source == NULL)
23464562236bSHarry Wentland 				return DC_NO_CLOCK_SOURCE_RESOURCE;
23474562236bSHarry Wentland 
23484562236bSHarry Wentland 			resource_reference_clock_source(
2349a2b8659dSTony Cheng 				&context->res_ctx, pool,
23504562236bSHarry Wentland 				pipe_ctx->clock_source);
23514562236bSHarry Wentland 
23524562236bSHarry Wentland 			/* only one cs per stream regardless of mpo */
23534562236bSHarry Wentland 			break;
23544562236bSHarry Wentland 		}
23554562236bSHarry Wentland 	}
23564562236bSHarry Wentland 
23574562236bSHarry Wentland 	return DC_OK;
23584562236bSHarry Wentland }
23594562236bSHarry Wentland 
23604562236bSHarry Wentland /*
23614562236bSHarry Wentland  * Note: We need to disable output if clock sources change,
23624562236bSHarry Wentland  * since bios does optimization and doesn't apply if changing
23634562236bSHarry Wentland  * PHY when not already disabled.
23644562236bSHarry Wentland  */
23654562236bSHarry Wentland bool pipe_need_reprogram(
23664562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx_old,
23674562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
23684562236bSHarry Wentland {
2369cfe4645eSDmytro Laktyushkin 	if (!pipe_ctx_old->stream)
2370cfe4645eSDmytro Laktyushkin 		return false;
2371cfe4645eSDmytro Laktyushkin 
23724562236bSHarry Wentland 	if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
23734562236bSHarry Wentland 		return true;
23744562236bSHarry Wentland 
23754562236bSHarry Wentland 	if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
23764562236bSHarry Wentland 		return true;
23774562236bSHarry Wentland 
23784562236bSHarry Wentland 	if (pipe_ctx_old->audio != pipe_ctx->audio)
23794562236bSHarry Wentland 		return true;
23804562236bSHarry Wentland 
23814562236bSHarry Wentland 	if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
23824562236bSHarry Wentland 			&& pipe_ctx_old->stream != pipe_ctx->stream)
23834562236bSHarry Wentland 		return true;
23844562236bSHarry Wentland 
23858e9c4c8cSHarry Wentland 	if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc)
23864562236bSHarry Wentland 		return true;
23874562236bSHarry Wentland 
23884562236bSHarry Wentland 	if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
23894562236bSHarry Wentland 		return true;
23904562236bSHarry Wentland 
23914562236bSHarry Wentland 
23924562236bSHarry Wentland 	return false;
23934562236bSHarry Wentland }
2394529cad0fSDing Wang 
23950971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
2396529cad0fSDing Wang 		struct bit_depth_reduction_params *fmt_bit_depth)
2397529cad0fSDing Wang {
23984fa086b9SLeo (Sunpeng) Li 	enum dc_dither_option option = stream->dither_option;
2399529cad0fSDing Wang 	enum dc_pixel_encoding pixel_encoding =
24004fa086b9SLeo (Sunpeng) Li 			stream->timing.pixel_encoding;
2401529cad0fSDing Wang 
2402529cad0fSDing Wang 	memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
2403529cad0fSDing Wang 
2404529cad0fSDing Wang 	if (option == DITHER_OPTION_DISABLE)
2405529cad0fSDing Wang 		return;
2406529cad0fSDing Wang 
2407529cad0fSDing Wang 	if (option == DITHER_OPTION_TRUN6) {
2408529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2409529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 0;
2410529cad0fSDing Wang 	} else if (option == DITHER_OPTION_TRUN8 ||
2411529cad0fSDing Wang 			option == DITHER_OPTION_TRUN8_SPATIAL6 ||
2412529cad0fSDing Wang 			option == DITHER_OPTION_TRUN8_FM6) {
2413529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2414529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 1;
2415529cad0fSDing Wang 	} else if (option == DITHER_OPTION_TRUN10        ||
2416529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL6   ||
2417529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8   ||
2418529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_FM8     ||
2419529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_FM6     ||
2420529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2421529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2422529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2423529cad0fSDing Wang 	}
2424529cad0fSDing Wang 
2425529cad0fSDing Wang 	/* special case - Formatter can only reduce by 4 bits at most.
2426529cad0fSDing Wang 	 * When reducing from 12 to 6 bits,
2427529cad0fSDing Wang 	 * HW recommends we use trunc with round mode
2428529cad0fSDing Wang 	 * (if we did nothing, trunc to 10 bits would be used)
2429529cad0fSDing Wang 	 * note that any 12->10 bit reduction is ignored prior to DCE8,
2430529cad0fSDing Wang 	 * as the input was 10 bits.
2431529cad0fSDing Wang 	 */
2432529cad0fSDing Wang 	if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM ||
2433529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL6 ||
2434529cad0fSDing Wang 			option == DITHER_OPTION_FM6) {
2435529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2436529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2437529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_MODE = 1;
2438529cad0fSDing Wang 	}
2439529cad0fSDing Wang 
2440529cad0fSDing Wang 	/* spatial dither
2441529cad0fSDing Wang 	 * note that spatial modes 1-3 are never used
2442529cad0fSDing Wang 	 */
2443529cad0fSDing Wang 	if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM            ||
2444529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL6 ||
2445529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL6      ||
2446529cad0fSDing Wang 			option == DITHER_OPTION_TRUN8_SPATIAL6) {
2447529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2448529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
2449529cad0fSDing Wang 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2450529cad0fSDing Wang 		fmt_bit_depth->flags.RGB_RANDOM =
2451529cad0fSDing Wang 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2452529cad0fSDing Wang 	} else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM            ||
2453529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL8 ||
2454529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL8_FM6        ||
2455529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8      ||
2456529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2457529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2458529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
2459529cad0fSDing Wang 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2460529cad0fSDing Wang 		fmt_bit_depth->flags.RGB_RANDOM =
2461529cad0fSDing Wang 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2462529cad0fSDing Wang 	} else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM ||
2463529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10 ||
2464529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10_FM8 ||
2465529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10_FM6) {
2466529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2467529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
2468529cad0fSDing Wang 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2469529cad0fSDing Wang 		fmt_bit_depth->flags.RGB_RANDOM =
2470529cad0fSDing Wang 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2471529cad0fSDing Wang 	}
2472529cad0fSDing Wang 
2473529cad0fSDing Wang 	if (option == DITHER_OPTION_SPATIAL6 ||
2474529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL8 ||
2475529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10) {
2476529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_RANDOM = 0;
2477529cad0fSDing Wang 	} else {
2478529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_RANDOM = 1;
2479529cad0fSDing Wang 	}
2480529cad0fSDing Wang 
2481529cad0fSDing Wang 	//////////////////////
2482529cad0fSDing Wang 	//// temporal dither
2483529cad0fSDing Wang 	//////////////////////
2484529cad0fSDing Wang 	if (option == DITHER_OPTION_FM6           ||
2485529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL8_FM6     ||
2486529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10_FM6     ||
2487529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_FM6     ||
2488529cad0fSDing Wang 			option == DITHER_OPTION_TRUN8_FM6      ||
2489529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2490529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2491529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0;
2492529cad0fSDing Wang 	} else if (option == DITHER_OPTION_FM8        ||
2493529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10_FM8  ||
2494529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_FM8) {
2495529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2496529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1;
2497529cad0fSDing Wang 	} else if (option == DITHER_OPTION_FM10) {
2498529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2499529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2;
2500529cad0fSDing Wang 	}
2501529cad0fSDing Wang 
2502529cad0fSDing Wang 	fmt_bit_depth->pixel_encoding = pixel_encoding;
2503529cad0fSDing Wang }
25049345d987SAndrey Grodzovsky 
25050971c40eSHarry Wentland bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream)
25069345d987SAndrey Grodzovsky {
25079345d987SAndrey Grodzovsky 	struct core_dc *core_dc = DC_TO_CORE(dc);
25089345d987SAndrey Grodzovsky 	struct dc_context *dc_ctx = core_dc->ctx;
25094fa086b9SLeo (Sunpeng) Li 	struct dc_link *link = stream->sink->link;
25109345d987SAndrey Grodzovsky 	struct timing_generator *tg = core_dc->res_pool->timing_generators[0];
25119345d987SAndrey Grodzovsky 	enum dc_status res = DC_OK;
25129345d987SAndrey Grodzovsky 
25134fa086b9SLeo (Sunpeng) Li 	calculate_phy_pix_clks(stream);
25149345d987SAndrey Grodzovsky 
25154fa086b9SLeo (Sunpeng) Li 	if (!tg->funcs->validate_timing(tg, &stream->timing))
25169345d987SAndrey Grodzovsky 		res = DC_FAIL_CONTROLLER_VALIDATE;
25179345d987SAndrey Grodzovsky 
25189345d987SAndrey Grodzovsky 	if (res == DC_OK)
25199345d987SAndrey Grodzovsky 		if (!link->link_enc->funcs->validate_output_with_stream(
25204fa086b9SLeo (Sunpeng) Li 						link->link_enc, stream))
25219345d987SAndrey Grodzovsky 			res = DC_FAIL_ENC_VALIDATE;
25229345d987SAndrey Grodzovsky 
25239345d987SAndrey Grodzovsky 	/* TODO: validate audio ASIC caps, encoder */
25249345d987SAndrey Grodzovsky 
25259345d987SAndrey Grodzovsky 	if (res == DC_OK)
25264fa086b9SLeo (Sunpeng) Li 		res = dc_link_validate_mode_timing(stream,
25279345d987SAndrey Grodzovsky 		      link,
25284fa086b9SLeo (Sunpeng) Li 		      &stream->timing);
25299345d987SAndrey Grodzovsky 
25309345d987SAndrey Grodzovsky 	if (res != DC_OK)
25319345d987SAndrey Grodzovsky 		DC_ERROR("Failed validation for stream %p, err:%d, !\n",
25329345d987SAndrey Grodzovsky 				stream, res);
25339345d987SAndrey Grodzovsky 
25349345d987SAndrey Grodzovsky 	return res == DC_OK;
25359345d987SAndrey Grodzovsky }
2536792671d7SAndrey Grodzovsky 
2537c9614aebSHarry Wentland bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state)
2538792671d7SAndrey Grodzovsky {
2539792671d7SAndrey Grodzovsky 	struct core_dc *core_dc = DC_TO_CORE(dc);
2540792671d7SAndrey Grodzovsky 
2541792671d7SAndrey Grodzovsky 	/* TODO For now validates pixel format only */
2542c9614aebSHarry Wentland 	if (core_dc->res_pool->funcs->validate_plane)
2543c9614aebSHarry Wentland 		return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK;
2544792671d7SAndrey Grodzovsky 
2545792671d7SAndrey Grodzovsky 	return true;
2546792671d7SAndrey Grodzovsky }
2547