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  */
254fc4dca8SSam Ravnborg 
264562236bSHarry Wentland #include "dm_services.h"
274562236bSHarry Wentland 
284562236bSHarry Wentland #include "resource.h"
294562236bSHarry Wentland #include "include/irq_service_interface.h"
304562236bSHarry Wentland #include "link_encoder.h"
314562236bSHarry Wentland #include "stream_encoder.h"
324562236bSHarry Wentland #include "opp.h"
334562236bSHarry Wentland #include "timing_generator.h"
344562236bSHarry Wentland #include "transform.h"
3533d7598dSJun Lei #include "dccg.h"
3633d7598dSJun Lei #include "dchubbub.h"
37d94585a0SYue Hin Lau #include "dpp.h"
385ac3d3c9SCharlene Liu #include "core_types.h"
394562236bSHarry Wentland #include "set_mode_types.h"
404562236bSHarry Wentland #include "virtual/virtual_stream_encoder.h"
413b94a400STao #include "dpcd_defs.h"
420d4b4253SJimmy Kizito #include "link_enc_cfg.h"
43d5a43956SWenjing Liu #include "link.h"
44fd249266SWenjing Liu #include "virtual/virtual_link_hwss.h"
45bc33f5e5SWenjing Liu #include "link/hwss/link_hwss_dio.h"
46bc33f5e5SWenjing Liu #include "link/hwss/link_hwss_dpia.h"
47bc33f5e5SWenjing Liu #include "link/hwss/link_hwss_hpo_dp.h"
48ad5594adSMichael Strauss #include "link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h"
49ad5594adSMichael Strauss #include "link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h"
504562236bSHarry Wentland 
51683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI)
52683b5950SMauro Rossi #include "dce60/dce60_resource.h"
53683b5950SMauro Rossi #endif
544562236bSHarry Wentland #include "dce80/dce80_resource.h"
554562236bSHarry Wentland #include "dce100/dce100_resource.h"
564562236bSHarry Wentland #include "dce110/dce110_resource.h"
574562236bSHarry Wentland #include "dce112/dce112_resource.h"
58cf2156e2SAlex Deucher #include "dce120/dce120_resource.h"
59ff5ef992SAlex Deucher #include "dcn10/dcn10_resource.h"
607ed4e635SHarry Wentland #include "dcn20/dcn20_resource.h"
61e22ece54SBhawanpreet Lakha #include "dcn21/dcn21_resource.h"
623f68c01bSZhan Liu #include "dcn201/dcn201_resource.h"
6320f2ffe5SAlex Deucher #include "dcn30/dcn30_resource.h"
6420f2ffe5SAlex Deucher #include "dcn301/dcn301_resource.h"
6520f2ffe5SAlex Deucher #include "dcn302/dcn302_resource.h"
66cd6d421eSAurabindo Pillai #include "dcn303/dcn303_resource.h"
678fe44c08SAlex Deucher #include "dcn31/dcn31_resource.h"
68ee7b62e1SRoman Li #include "dcn314/dcn314_resource.h"
69501867d0SQingqing Zhuo #include "dcn315/dcn315_resource.h"
70c477eaa6SHansen Dsouza #include "dcn316/dcn316_resource.h"
71d3dfceb5SAurabindo Pillai #include "../dcn32/dcn32_resource.h"
72d3dfceb5SAurabindo Pillai #include "../dcn321/dcn321_resource.h"
735d4b05ddSBhawanpreet Lakha 
740f3b9542SWenjing Liu #define VISUAL_CONFIRM_BASE_DEFAULT 3
750f3b9542SWenjing Liu #define VISUAL_CONFIRM_BASE_MIN 1
760f3b9542SWenjing Liu #define VISUAL_CONFIRM_BASE_MAX 10
77c5a4f901SWenjing Liu /* we choose 240 because it is a common denominator of common v addressable
78c5a4f901SWenjing Liu  * such as 2160, 1440, 1200, 960. So we take 1/240 portion of v addressable as
79c5a4f901SWenjing Liu  * the visual confirm dpp offset height. So visual confirm height can stay
80c5a4f901SWenjing Liu  * relatively the same independent from timing used.
81c5a4f901SWenjing Liu  */
82c5a4f901SWenjing Liu #define VISUAL_CONFIRM_DPP_OFFSET_DENO 240
831068e987SLeo (Hanghong) Ma 
845d4b05ddSBhawanpreet Lakha #define DC_LOGGER_INIT(logger)
855d4b05ddSBhawanpreet Lakha 
8675bd42fdSEthan Bitnun #define UNABLE_TO_SPLIT -1
8775bd42fdSEthan Bitnun 
resource_parse_asic_id(struct hw_asic_id asic_id)884562236bSHarry Wentland enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
894562236bSHarry Wentland {
904562236bSHarry Wentland 	enum dce_version dc_version = DCE_VERSION_UNKNOWN;
9177299956SRoman Li 
924562236bSHarry Wentland 	switch (asic_id.chip_family) {
934562236bSHarry Wentland 
94683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI)
95683b5950SMauro Rossi 	case FAMILY_SI:
96683b5950SMauro Rossi 		if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) ||
97683b5950SMauro Rossi 		    ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) ||
98683b5950SMauro Rossi 		    ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev))
99683b5950SMauro Rossi 			dc_version = DCE_VERSION_6_0;
100683b5950SMauro Rossi 		else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev))
101683b5950SMauro Rossi 			dc_version = DCE_VERSION_6_4;
102683b5950SMauro Rossi 		else
103683b5950SMauro Rossi 			dc_version = DCE_VERSION_6_1;
104683b5950SMauro Rossi 		break;
105683b5950SMauro Rossi #endif
1064562236bSHarry Wentland 	case FAMILY_CI:
1074562236bSHarry Wentland 		dc_version = DCE_VERSION_8_0;
1084562236bSHarry Wentland 		break;
109ebfdf0d0SAlex Deucher 	case FAMILY_KV:
110ebfdf0d0SAlex Deucher 		if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) ||
111ebfdf0d0SAlex Deucher 		    ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) ||
112ebfdf0d0SAlex Deucher 		    ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev))
113ebfdf0d0SAlex Deucher 			dc_version = DCE_VERSION_8_3;
114ebfdf0d0SAlex Deucher 		else
115ebfdf0d0SAlex Deucher 			dc_version = DCE_VERSION_8_1;
116ebfdf0d0SAlex Deucher 		break;
1174562236bSHarry Wentland 	case FAMILY_CZ:
1184562236bSHarry Wentland 		dc_version = DCE_VERSION_11_0;
1194562236bSHarry Wentland 		break;
1204562236bSHarry Wentland 
1214562236bSHarry Wentland 	case FAMILY_VI:
1224562236bSHarry Wentland 		if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
1234562236bSHarry Wentland 				ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
1244562236bSHarry Wentland 			dc_version = DCE_VERSION_10_0;
1254562236bSHarry Wentland 			break;
1264562236bSHarry Wentland 		}
1274562236bSHarry Wentland 		if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
128b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
129b264d345SJordan Lazare 				ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
1304562236bSHarry Wentland 			dc_version = DCE_VERSION_11_2;
1314562236bSHarry Wentland 		}
1320c75d5acSJerry (Fangzhi) Zuo 		if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev))
1330c75d5acSJerry (Fangzhi) Zuo 			dc_version = DCE_VERSION_11_22;
1344562236bSHarry Wentland 		break;
1352c8ad2d5SAlex Deucher 	case FAMILY_AI:
136b8b6ce89SLeo Li 		if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev))
137b8b6ce89SLeo Li 			dc_version = DCE_VERSION_12_1;
138b8b6ce89SLeo Li 		else
1392c8ad2d5SAlex Deucher 			dc_version = DCE_VERSION_12_0;
1402c8ad2d5SAlex Deucher 		break;
141ff5ef992SAlex Deucher 	case FAMILY_RV:
142ff5ef992SAlex Deucher 		dc_version = DCN_VERSION_1_0;
1430e3d73f1SBhawanpreet Lakha 		if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev))
1440e3d73f1SBhawanpreet Lakha 			dc_version = DCN_VERSION_1_01;
145e22ece54SBhawanpreet Lakha 		if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev))
146e22ece54SBhawanpreet Lakha 			dc_version = DCN_VERSION_2_1;
1479ba93114SRoman Li 		if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev))
1489ba93114SRoman Li 			dc_version = DCN_VERSION_2_1;
149ff5ef992SAlex Deucher 		break;
1507ed4e635SHarry Wentland 
1517ed4e635SHarry Wentland 	case FAMILY_NV:
1527ed4e635SHarry Wentland 		dc_version = DCN_VERSION_2_0;
153fd22013aSOliver Logush 		if (asic_id.chip_id == DEVICE_ID_NV_13FE || asic_id.chip_id == DEVICE_ID_NV_143F) {
1543f68c01bSZhan Liu 			dc_version = DCN_VERSION_2_01;
1553f68c01bSZhan Liu 			break;
1563f68c01bSZhan Liu 		}
1575dba4991SBhawanpreet Lakha 		if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev))
1585dba4991SBhawanpreet Lakha 			dc_version = DCN_VERSION_3_0;
15936d26912SBhawanpreet Lakha 		if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev))
16036d26912SBhawanpreet Lakha 			dc_version = DCN_VERSION_3_02;
161cd6d421eSAurabindo Pillai 		if (ASICREV_IS_BEIGE_GOBY_P(asic_id.hw_internal_rev))
162cd6d421eSAurabindo Pillai 			dc_version = DCN_VERSION_3_03;
1637ed4e635SHarry Wentland 		break;
1643a83e4e6SRoman Li 
1653a83e4e6SRoman Li 	case FAMILY_VGH:
1663a83e4e6SRoman Li 		dc_version = DCN_VERSION_3_01;
1673a83e4e6SRoman Li 		break;
1682083640fSNicholas Kazlauskas 
1692083640fSNicholas Kazlauskas 	case FAMILY_YELLOW_CARP:
1702083640fSNicholas Kazlauskas 		if (ASICREV_IS_YELLOW_CARP(asic_id.hw_internal_rev))
1712083640fSNicholas Kazlauskas 			dc_version = DCN_VERSION_3_1;
1722083640fSNicholas Kazlauskas 		break;
173501867d0SQingqing Zhuo 	case AMDGPU_FAMILY_GC_10_3_6:
174501867d0SQingqing Zhuo 		if (ASICREV_IS_GC_10_3_6(asic_id.hw_internal_rev))
175501867d0SQingqing Zhuo 			dc_version = DCN_VERSION_3_15;
176501867d0SQingqing Zhuo 		break;
177de7cc1b4SPrike Liang 	case AMDGPU_FAMILY_GC_10_3_7:
178de7cc1b4SPrike Liang 		if (ASICREV_IS_GC_10_3_7(asic_id.hw_internal_rev))
179de7cc1b4SPrike Liang 			dc_version = DCN_VERSION_3_16;
180de7cc1b4SPrike Liang 		break;
181d3dfceb5SAurabindo Pillai 	case AMDGPU_FAMILY_GC_11_0_0:
182d3dfceb5SAurabindo Pillai 		dc_version = DCN_VERSION_3_2;
183d3dfceb5SAurabindo Pillai 		if (ASICREV_IS_GC_11_0_2(asic_id.hw_internal_rev))
184d3dfceb5SAurabindo Pillai 			dc_version = DCN_VERSION_3_21;
185d3dfceb5SAurabindo Pillai 		break;
18608ebadfcSYifan Zhang 	case AMDGPU_FAMILY_GC_11_0_1:
187ee7b62e1SRoman Li 		dc_version = DCN_VERSION_3_14;
188ee7b62e1SRoman Li 		break;
1894562236bSHarry Wentland 	default:
1904562236bSHarry Wentland 		dc_version = DCE_VERSION_UNKNOWN;
1914562236bSHarry Wentland 		break;
1924562236bSHarry Wentland 	}
1934562236bSHarry Wentland 	return dc_version;
1944562236bSHarry Wentland }
1954562236bSHarry Wentland 
dc_create_resource_pool(struct dc * dc,const struct dc_init_data * init_data,enum dce_version dc_version)196d9673c92SHarry Wentland struct resource_pool *dc_create_resource_pool(struct dc  *dc,
197d9673c92SHarry Wentland 					      const struct dc_init_data *init_data,
198d9673c92SHarry Wentland 					      enum dce_version dc_version)
1994562236bSHarry Wentland {
2005ac3d3c9SCharlene Liu 	struct resource_pool *res_pool = NULL;
2014562236bSHarry Wentland 
2024562236bSHarry Wentland 	switch (dc_version) {
203683b5950SMauro Rossi #if defined(CONFIG_DRM_AMD_DC_SI)
204683b5950SMauro Rossi 	case DCE_VERSION_6_0:
205683b5950SMauro Rossi 		res_pool = dce60_create_resource_pool(
206683b5950SMauro Rossi 			init_data->num_virtual_links, dc);
207683b5950SMauro Rossi 		break;
208683b5950SMauro Rossi 	case DCE_VERSION_6_1:
209683b5950SMauro Rossi 		res_pool = dce61_create_resource_pool(
210683b5950SMauro Rossi 			init_data->num_virtual_links, dc);
211683b5950SMauro Rossi 		break;
212683b5950SMauro Rossi 	case DCE_VERSION_6_4:
213683b5950SMauro Rossi 		res_pool = dce64_create_resource_pool(
214683b5950SMauro Rossi 			init_data->num_virtual_links, dc);
215683b5950SMauro Rossi 		break;
216683b5950SMauro Rossi #endif
2174562236bSHarry Wentland 	case DCE_VERSION_8_0:
2185ac3d3c9SCharlene Liu 		res_pool = dce80_create_resource_pool(
219d9673c92SHarry Wentland 				init_data->num_virtual_links, dc);
2205ac3d3c9SCharlene Liu 		break;
2217992a629SAlex Deucher 	case DCE_VERSION_8_1:
2227992a629SAlex Deucher 		res_pool = dce81_create_resource_pool(
223d9673c92SHarry Wentland 				init_data->num_virtual_links, dc);
2247992a629SAlex Deucher 		break;
2257992a629SAlex Deucher 	case DCE_VERSION_8_3:
2267992a629SAlex Deucher 		res_pool = dce83_create_resource_pool(
227d9673c92SHarry Wentland 				init_data->num_virtual_links, dc);
2287992a629SAlex Deucher 		break;
2294562236bSHarry Wentland 	case DCE_VERSION_10_0:
2305ac3d3c9SCharlene Liu 		res_pool = dce100_create_resource_pool(
231d9673c92SHarry Wentland 				init_data->num_virtual_links, dc);
2325ac3d3c9SCharlene Liu 		break;
2334562236bSHarry Wentland 	case DCE_VERSION_11_0:
2345ac3d3c9SCharlene Liu 		res_pool = dce110_create_resource_pool(
235d9673c92SHarry Wentland 				init_data->num_virtual_links, dc,
236d9673c92SHarry Wentland 				init_data->asic_id);
2375ac3d3c9SCharlene Liu 		break;
2384562236bSHarry Wentland 	case DCE_VERSION_11_2:
2390c75d5acSJerry (Fangzhi) Zuo 	case DCE_VERSION_11_22:
2405ac3d3c9SCharlene Liu 		res_pool = dce112_create_resource_pool(
241d9673c92SHarry Wentland 				init_data->num_virtual_links, dc);
2425ac3d3c9SCharlene Liu 		break;
2432c8ad2d5SAlex Deucher 	case DCE_VERSION_12_0:
244b8b6ce89SLeo Li 	case DCE_VERSION_12_1:
2452c8ad2d5SAlex Deucher 		res_pool = dce120_create_resource_pool(
246d9673c92SHarry Wentland 				init_data->num_virtual_links, dc);
2472c8ad2d5SAlex Deucher 		break;
248ff5ef992SAlex Deucher 
2494652ae7aSHarry Wentland #if defined(CONFIG_DRM_AMD_DC_FP)
250ff5ef992SAlex Deucher 	case DCN_VERSION_1_0:
2510e3d73f1SBhawanpreet Lakha 	case DCN_VERSION_1_01:
252d9673c92SHarry Wentland 		res_pool = dcn10_create_resource_pool(init_data, dc);
253ff5ef992SAlex Deucher 		break;
2547ed4e635SHarry Wentland 	case DCN_VERSION_2_0:
2557ed4e635SHarry Wentland 		res_pool = dcn20_create_resource_pool(init_data, dc);
2567ed4e635SHarry Wentland 		break;
257e22ece54SBhawanpreet Lakha 	case DCN_VERSION_2_1:
258e22ece54SBhawanpreet Lakha 		res_pool = dcn21_create_resource_pool(init_data, dc);
259e22ece54SBhawanpreet Lakha 		break;
2603f68c01bSZhan Liu 	case DCN_VERSION_2_01:
2613f68c01bSZhan Liu 		res_pool = dcn201_create_resource_pool(init_data, dc);
2623f68c01bSZhan Liu 		break;
2635dba4991SBhawanpreet Lakha 	case DCN_VERSION_3_0:
2645dba4991SBhawanpreet Lakha 		res_pool = dcn30_create_resource_pool(init_data, dc);
2655dba4991SBhawanpreet Lakha 		break;
2663a83e4e6SRoman Li 	case DCN_VERSION_3_01:
2673a83e4e6SRoman Li 		res_pool = dcn301_create_resource_pool(init_data, dc);
2683a83e4e6SRoman Li 		break;
26936d26912SBhawanpreet Lakha 	case DCN_VERSION_3_02:
27036d26912SBhawanpreet Lakha 		res_pool = dcn302_create_resource_pool(init_data, dc);
27136d26912SBhawanpreet Lakha 		break;
272cd6d421eSAurabindo Pillai 	case DCN_VERSION_3_03:
273cd6d421eSAurabindo Pillai 		res_pool = dcn303_create_resource_pool(init_data, dc);
274cd6d421eSAurabindo Pillai 		break;
2752083640fSNicholas Kazlauskas 	case DCN_VERSION_3_1:
2762083640fSNicholas Kazlauskas 		res_pool = dcn31_create_resource_pool(init_data, dc);
2772083640fSNicholas Kazlauskas 		break;
278ee7b62e1SRoman Li 	case DCN_VERSION_3_14:
279ee7b62e1SRoman Li 		res_pool = dcn314_create_resource_pool(init_data, dc);
280ee7b62e1SRoman Li 		break;
281501867d0SQingqing Zhuo 	case DCN_VERSION_3_15:
282501867d0SQingqing Zhuo 		res_pool = dcn315_create_resource_pool(init_data, dc);
283501867d0SQingqing Zhuo 		break;
284c477eaa6SHansen Dsouza 	case DCN_VERSION_3_16:
285c477eaa6SHansen Dsouza 		res_pool = dcn316_create_resource_pool(init_data, dc);
286c477eaa6SHansen Dsouza 		break;
287d3dfceb5SAurabindo Pillai 	case DCN_VERSION_3_2:
288d3dfceb5SAurabindo Pillai 		res_pool = dcn32_create_resource_pool(init_data, dc);
289d3dfceb5SAurabindo Pillai 		break;
290d3dfceb5SAurabindo Pillai 	case DCN_VERSION_3_21:
291d3dfceb5SAurabindo Pillai 		res_pool = dcn321_create_resource_pool(init_data, dc);
292d3dfceb5SAurabindo Pillai 		break;
2934652ae7aSHarry Wentland #endif /* CONFIG_DRM_AMD_DC_FP */
2944562236bSHarry Wentland 	default:
2954562236bSHarry Wentland 		break;
2964562236bSHarry Wentland 	}
297f49cfa27Shersen wu 
2985ac3d3c9SCharlene Liu 	if (res_pool != NULL) {
2999adc8050SDmytro Laktyushkin 		if (dc->ctx->dc_bios->fw_info_valid) {
30041a5a2a8Shersen wu 			res_pool->ref_clocks.xtalin_clock_inKhz =
3019adc8050SDmytro Laktyushkin 				dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
30241a5a2a8Shersen wu 			/* initialize with firmware data first, no all
30341a5a2a8Shersen wu 			 * ASIC have DCCG SW component. FPGA or
30441a5a2a8Shersen wu 			 * simulation need initialization of
30541a5a2a8Shersen wu 			 * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz
30641a5a2a8Shersen wu 			 * with xtalin_clock_inKhz
30741a5a2a8Shersen wu 			 */
30841a5a2a8Shersen wu 			res_pool->ref_clocks.dccg_ref_clock_inKhz =
30941a5a2a8Shersen wu 				res_pool->ref_clocks.xtalin_clock_inKhz;
31041a5a2a8Shersen wu 			res_pool->ref_clocks.dchub_ref_clock_inKhz =
31141a5a2a8Shersen wu 				res_pool->ref_clocks.xtalin_clock_inKhz;
3125ac3d3c9SCharlene Liu 		} else
3135ac3d3c9SCharlene Liu 			ASSERT_CRITICAL(false);
3145ac3d3c9SCharlene Liu 	}
3155ac3d3c9SCharlene Liu 
3165ac3d3c9SCharlene Liu 	return res_pool;
3174562236bSHarry Wentland }
3184562236bSHarry Wentland 
dc_destroy_resource_pool(struct dc * dc)319fb3466a4SBhawanpreet Lakha void dc_destroy_resource_pool(struct dc  *dc)
3204562236bSHarry Wentland {
3214562236bSHarry Wentland 	if (dc) {
3224562236bSHarry Wentland 		if (dc->res_pool)
3234562236bSHarry Wentland 			dc->res_pool->funcs->destroy(&dc->res_pool);
3244562236bSHarry Wentland 
3252004f45eSHarry Wentland 		kfree(dc->hwseq);
3264562236bSHarry Wentland 	}
3274562236bSHarry Wentland }
3284562236bSHarry Wentland 
update_num_audio(const struct resource_straps * straps,unsigned int * num_audio,struct audio_support * aud_support)3294562236bSHarry Wentland static void update_num_audio(
3304562236bSHarry Wentland 	const struct resource_straps *straps,
3314562236bSHarry Wentland 	unsigned int *num_audio,
3324562236bSHarry Wentland 	struct audio_support *aud_support)
3334562236bSHarry Wentland {
3344562236bSHarry Wentland 	aud_support->dp_audio = true;
335b8e9eb72SCharlene Liu 	aud_support->hdmi_audio_native = false;
336b8e9eb72SCharlene Liu 	aud_support->hdmi_audio_on_dongle = false;
337b8e9eb72SCharlene Liu 
338b8e9eb72SCharlene Liu 	if (straps->hdmi_disable == 0) {
3394562236bSHarry Wentland 		if (straps->dc_pinstraps_audio & 0x2) {
3404562236bSHarry Wentland 			aud_support->hdmi_audio_on_dongle = true;
341b8e9eb72SCharlene Liu 			aud_support->hdmi_audio_native = true;
3424562236bSHarry Wentland 		}
3434562236bSHarry Wentland 	}
3444562236bSHarry Wentland 
3454562236bSHarry Wentland 	switch (straps->audio_stream_number) {
3464562236bSHarry Wentland 	case 0: /* multi streams supported */
3474562236bSHarry Wentland 		break;
3484562236bSHarry Wentland 	case 1: /* multi streams not supported */
3494562236bSHarry Wentland 		*num_audio = 1;
3504562236bSHarry Wentland 		break;
3514562236bSHarry Wentland 	default:
3524562236bSHarry Wentland 		DC_ERR("DC: unexpected audio fuse!\n");
35317a96033SJulia Lawall 	}
3544562236bSHarry Wentland }
3554562236bSHarry Wentland 
resource_construct(unsigned int num_virtual_links,struct dc * dc,struct resource_pool * pool,const struct resource_create_funcs * create_funcs)3564562236bSHarry Wentland bool resource_construct(
3574562236bSHarry Wentland 	unsigned int num_virtual_links,
358fb3466a4SBhawanpreet Lakha 	struct dc  *dc,
3594562236bSHarry Wentland 	struct resource_pool *pool,
3604562236bSHarry Wentland 	const struct resource_create_funcs *create_funcs)
3614562236bSHarry Wentland {
3624562236bSHarry Wentland 	struct dc_context *ctx = dc->ctx;
3634562236bSHarry Wentland 	const struct resource_caps *caps = pool->res_cap;
3644562236bSHarry Wentland 	int i;
3654562236bSHarry Wentland 	unsigned int num_audio = caps->num_audio;
3664562236bSHarry Wentland 	struct resource_straps straps = {0};
3674562236bSHarry Wentland 
3684562236bSHarry Wentland 	if (create_funcs->read_dce_straps)
3694562236bSHarry Wentland 		create_funcs->read_dce_straps(dc->ctx, &straps);
3704562236bSHarry Wentland 
3714562236bSHarry Wentland 	pool->audio_count = 0;
3724562236bSHarry Wentland 	if (create_funcs->create_audio) {
3734562236bSHarry Wentland 		/* find the total number of streams available via the
3744562236bSHarry Wentland 		 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
3754562236bSHarry Wentland 		 * registers (one for each pin) starting from pin 1
3764562236bSHarry Wentland 		 * up to the max number of audio pins.
3774562236bSHarry Wentland 		 * We stop on the first pin where
3784562236bSHarry Wentland 		 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
3794562236bSHarry Wentland 		 */
3804562236bSHarry Wentland 		update_num_audio(&straps, &num_audio, &pool->audio_support);
3815feb9f07STai Man 		for (i = 0; i < caps->num_audio; i++) {
3824562236bSHarry Wentland 			struct audio *aud = create_funcs->create_audio(ctx, i);
3834562236bSHarry Wentland 
3844562236bSHarry Wentland 			if (aud == NULL) {
3854562236bSHarry Wentland 				DC_ERR("DC: failed to create audio!\n");
3864562236bSHarry Wentland 				return false;
3874562236bSHarry Wentland 			}
3884562236bSHarry Wentland 			if (!aud->funcs->endpoint_valid(aud)) {
3894562236bSHarry Wentland 				aud->funcs->destroy(&aud);
3904562236bSHarry Wentland 				break;
3914562236bSHarry Wentland 			}
3924562236bSHarry Wentland 			pool->audios[i] = aud;
3934562236bSHarry Wentland 			pool->audio_count++;
3944562236bSHarry Wentland 		}
3954562236bSHarry Wentland 	}
3964562236bSHarry Wentland 
3974562236bSHarry Wentland 	pool->stream_enc_count = 0;
3984562236bSHarry Wentland 	if (create_funcs->create_stream_encoder) {
3994562236bSHarry Wentland 		for (i = 0; i < caps->num_stream_encoder; i++) {
4004562236bSHarry Wentland 			pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
4014562236bSHarry Wentland 			if (pool->stream_enc[i] == NULL)
4024562236bSHarry Wentland 				DC_ERR("DC: failed to create stream_encoder!\n");
4034562236bSHarry Wentland 			pool->stream_enc_count++;
4044562236bSHarry Wentland 		}
4054562236bSHarry Wentland 	}
406929c3aaaSEric Bernstein 
407f01ee019SFangzhi Zuo 	pool->hpo_dp_stream_enc_count = 0;
408f01ee019SFangzhi Zuo 	if (create_funcs->create_hpo_dp_stream_encoder) {
409f01ee019SFangzhi Zuo 		for (i = 0; i < caps->num_hpo_dp_stream_encoder; i++) {
410f01ee019SFangzhi Zuo 			pool->hpo_dp_stream_enc[i] = create_funcs->create_hpo_dp_stream_encoder(i+ENGINE_ID_HPO_DP_0, ctx);
411f01ee019SFangzhi Zuo 			if (pool->hpo_dp_stream_enc[i] == NULL)
412f01ee019SFangzhi Zuo 				DC_ERR("DC: failed to create HPO DP stream encoder!\n");
413f01ee019SFangzhi Zuo 			pool->hpo_dp_stream_enc_count++;
414f01ee019SFangzhi Zuo 
415f01ee019SFangzhi Zuo 		}
416f01ee019SFangzhi Zuo 	}
417f01ee019SFangzhi Zuo 
418f01ee019SFangzhi Zuo 	pool->hpo_dp_link_enc_count = 0;
419f01ee019SFangzhi Zuo 	if (create_funcs->create_hpo_dp_link_encoder) {
420f01ee019SFangzhi Zuo 		for (i = 0; i < caps->num_hpo_dp_link_encoder; i++) {
421f01ee019SFangzhi Zuo 			pool->hpo_dp_link_enc[i] = create_funcs->create_hpo_dp_link_encoder(i, ctx);
422f01ee019SFangzhi Zuo 			if (pool->hpo_dp_link_enc[i] == NULL)
423f01ee019SFangzhi Zuo 				DC_ERR("DC: failed to create HPO DP link encoder!\n");
424f01ee019SFangzhi Zuo 			pool->hpo_dp_link_enc_count++;
425f01ee019SFangzhi Zuo 		}
426f01ee019SFangzhi Zuo 	}
427f01ee019SFangzhi Zuo 
4285dba4991SBhawanpreet Lakha 	for (i = 0; i < caps->num_mpc_3dlut; i++) {
4295dba4991SBhawanpreet Lakha 		pool->mpc_lut[i] = dc_create_3dlut_func();
4305dba4991SBhawanpreet Lakha 		if (pool->mpc_lut[i] == NULL)
4315dba4991SBhawanpreet Lakha 			DC_ERR("DC: failed to create MPC 3dlut!\n");
4325dba4991SBhawanpreet Lakha 		pool->mpc_shaper[i] = dc_create_transfer_func();
4335dba4991SBhawanpreet Lakha 		if (pool->mpc_shaper[i] == NULL)
4345dba4991SBhawanpreet Lakha 			DC_ERR("DC: failed to create MPC shaper!\n");
4355dba4991SBhawanpreet Lakha 	}
43659b8ca24SAlex Hung 
4374176664bSCharlene Liu 	dc->caps.dynamic_audio = false;
4384176664bSCharlene Liu 	if (pool->audio_count < pool->stream_enc_count) {
4394176664bSCharlene Liu 		dc->caps.dynamic_audio = true;
4404176664bSCharlene Liu 	}
4414562236bSHarry Wentland 	for (i = 0; i < num_virtual_links; i++) {
4424562236bSHarry Wentland 		pool->stream_enc[pool->stream_enc_count] =
4434562236bSHarry Wentland 			virtual_stream_encoder_create(
4444562236bSHarry Wentland 					ctx, ctx->dc_bios);
4454562236bSHarry Wentland 		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
4464562236bSHarry Wentland 			DC_ERR("DC: failed to create stream_encoder!\n");
4474562236bSHarry Wentland 			return false;
4484562236bSHarry Wentland 		}
4494562236bSHarry Wentland 		pool->stream_enc_count++;
4504562236bSHarry Wentland 	}
4514562236bSHarry Wentland 
4524562236bSHarry Wentland 	dc->hwseq = create_funcs->create_hwseq(ctx);
4534562236bSHarry Wentland 
4544562236bSHarry Wentland 	return true;
4554562236bSHarry Wentland }
find_matching_clock_source(const struct resource_pool * pool,struct clock_source * clock_source)456ad8960a6SMikita Lipski static int find_matching_clock_source(
457ad8960a6SMikita Lipski 		const struct resource_pool *pool,
458ad8960a6SMikita Lipski 		struct clock_source *clock_source)
459ad8960a6SMikita Lipski {
4604562236bSHarry Wentland 
461ad8960a6SMikita Lipski 	int i;
462ad8960a6SMikita Lipski 
463ad8960a6SMikita Lipski 	for (i = 0; i < pool->clk_src_count; i++) {
464ad8960a6SMikita Lipski 		if (pool->clock_sources[i] == clock_source)
465ad8960a6SMikita Lipski 			return i;
466ad8960a6SMikita Lipski 	}
467ad8960a6SMikita Lipski 	return -1;
468ad8960a6SMikita Lipski }
4694562236bSHarry Wentland 
resource_unreference_clock_source(struct resource_context * res_ctx,const struct resource_pool * pool,struct clock_source * clock_source)47021e67d4dSHarry Wentland void resource_unreference_clock_source(
4714562236bSHarry Wentland 		struct resource_context *res_ctx,
472a2b8659dSTony Cheng 		const struct resource_pool *pool,
4734a629536SHarry Wentland 		struct clock_source *clock_source)
4744562236bSHarry Wentland {
475ad8960a6SMikita Lipski 	int i = find_matching_clock_source(pool, clock_source);
4764a629536SHarry Wentland 
477ad8960a6SMikita Lipski 	if (i > -1)
4784562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]--;
4794562236bSHarry Wentland 
48021e67d4dSHarry Wentland 	if (pool->dp_clock_source == clock_source)
4814562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count--;
4824562236bSHarry Wentland }
4834562236bSHarry Wentland 
resource_reference_clock_source(struct resource_context * res_ctx,const struct resource_pool * pool,struct clock_source * clock_source)4844562236bSHarry Wentland void resource_reference_clock_source(
4854562236bSHarry Wentland 		struct resource_context *res_ctx,
486a2b8659dSTony Cheng 		const struct resource_pool *pool,
4874562236bSHarry Wentland 		struct clock_source *clock_source)
4884562236bSHarry Wentland {
489ad8960a6SMikita Lipski 	int i = find_matching_clock_source(pool, clock_source);
4904562236bSHarry Wentland 
491ad8960a6SMikita Lipski 	if (i > -1)
4924562236bSHarry Wentland 		res_ctx->clock_source_ref_count[i]++;
4934562236bSHarry Wentland 
494a2b8659dSTony Cheng 	if (pool->dp_clock_source == clock_source)
4954562236bSHarry Wentland 		res_ctx->dp_clock_source_ref_count++;
4964562236bSHarry Wentland }
4974562236bSHarry Wentland 
resource_get_clock_source_reference(struct resource_context * res_ctx,const struct resource_pool * pool,struct clock_source * clock_source)498ad8960a6SMikita Lipski int resource_get_clock_source_reference(
499ad8960a6SMikita Lipski 		struct resource_context *res_ctx,
500ad8960a6SMikita Lipski 		const struct resource_pool *pool,
501ad8960a6SMikita Lipski 		struct clock_source *clock_source)
502ad8960a6SMikita Lipski {
503ad8960a6SMikita Lipski 	int i = find_matching_clock_source(pool, clock_source);
504ad8960a6SMikita Lipski 
505ad8960a6SMikita Lipski 	if (i > -1)
506ad8960a6SMikita Lipski 		return res_ctx->clock_source_ref_count[i];
507ad8960a6SMikita Lipski 
508ad8960a6SMikita Lipski 	if (pool->dp_clock_source == clock_source)
509ad8960a6SMikita Lipski 		return res_ctx->dp_clock_source_ref_count;
510ad8960a6SMikita Lipski 
511ad8960a6SMikita Lipski 	return -1;
512ad8960a6SMikita Lipski }
513ad8960a6SMikita Lipski 
resource_are_vblanks_synchronizable(struct dc_stream_state * stream1,struct dc_stream_state * stream2)51477a2b726SVladimir Stempen bool resource_are_vblanks_synchronizable(
51577a2b726SVladimir Stempen 	struct dc_stream_state *stream1,
51677a2b726SVladimir Stempen 	struct dc_stream_state *stream2)
51777a2b726SVladimir Stempen {
51877a2b726SVladimir Stempen 	uint32_t base60_refresh_rates[] = {10, 20, 5};
51977a2b726SVladimir Stempen 	uint8_t i;
520d0b3bbd3SJiapeng Chong 	uint8_t rr_count = ARRAY_SIZE(base60_refresh_rates);
521783bf403SVladimir Stempen 	uint64_t frame_time_diff;
52277a2b726SVladimir Stempen 
52377a2b726SVladimir Stempen 	if (stream1->ctx->dc->config.vblank_alignment_dto_params &&
52477a2b726SVladimir Stempen 		stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&
52577a2b726SVladimir Stempen 		dc_is_dp_signal(stream1->signal) &&
52677a2b726SVladimir Stempen 		dc_is_dp_signal(stream2->signal) &&
52777a2b726SVladimir Stempen 		false == stream1->has_non_synchronizable_pclk &&
52877a2b726SVladimir Stempen 		false == stream2->has_non_synchronizable_pclk &&
52977a2b726SVladimir Stempen 		stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&
53077a2b726SVladimir Stempen 		stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {
53177a2b726SVladimir Stempen 		/* disable refresh rates higher than 60Hz for now */
53277a2b726SVladimir Stempen 		if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/
53377a2b726SVladimir Stempen 				stream1->timing.v_total > 60)
53477a2b726SVladimir Stempen 			return false;
53577a2b726SVladimir Stempen 		if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/
53677a2b726SVladimir Stempen 				stream2->timing.v_total > 60)
53777a2b726SVladimir Stempen 			return false;
538783bf403SVladimir Stempen 		frame_time_diff = (uint64_t)10000 *
53977a2b726SVladimir Stempen 			stream1->timing.h_total *
54077a2b726SVladimir Stempen 			stream1->timing.v_total *
541783bf403SVladimir Stempen 			stream2->timing.pix_clk_100hz;
542783bf403SVladimir Stempen 		frame_time_diff = div_u64(frame_time_diff, stream1->timing.pix_clk_100hz);
543783bf403SVladimir Stempen 		frame_time_diff = div_u64(frame_time_diff, stream2->timing.h_total);
544783bf403SVladimir Stempen 		frame_time_diff = div_u64(frame_time_diff, stream2->timing.v_total);
54577a2b726SVladimir Stempen 		for (i = 0; i < rr_count; i++) {
546783bf403SVladimir Stempen 			int64_t diff = (int64_t)div_u64(frame_time_diff * base60_refresh_rates[i], 10) - 10000;
54777a2b726SVladimir Stempen 
54877a2b726SVladimir Stempen 			if (diff < 0)
54977a2b726SVladimir Stempen 				diff = -diff;
55077a2b726SVladimir Stempen 			if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)
55177a2b726SVladimir Stempen 				return true;
55277a2b726SVladimir Stempen 		}
55377a2b726SVladimir Stempen 	}
55477a2b726SVladimir Stempen 	return false;
55577a2b726SVladimir Stempen }
55677a2b726SVladimir Stempen 
resource_are_streams_timing_synchronizable(struct dc_stream_state * stream1,struct dc_stream_state * stream2)5574562236bSHarry Wentland bool resource_are_streams_timing_synchronizable(
5580971c40eSHarry Wentland 	struct dc_stream_state *stream1,
5590971c40eSHarry Wentland 	struct dc_stream_state *stream2)
5604562236bSHarry Wentland {
5614fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.h_total != stream2->timing.h_total)
5624562236bSHarry Wentland 		return false;
5634562236bSHarry Wentland 
5644fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.v_total != stream2->timing.v_total)
5654562236bSHarry Wentland 		return false;
5664562236bSHarry Wentland 
5674fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.h_addressable
5684fa086b9SLeo (Sunpeng) Li 				!= stream2->timing.h_addressable)
5694562236bSHarry Wentland 		return false;
5704562236bSHarry Wentland 
5714fa086b9SLeo (Sunpeng) Li 	if (stream1->timing.v_addressable
5724fa086b9SLeo (Sunpeng) Li 				!= stream2->timing.v_addressable)
5734562236bSHarry Wentland 		return false;
5744562236bSHarry Wentland 
5758582aea2SDavid Galiffi 	if (stream1->timing.v_front_porch
5768582aea2SDavid Galiffi 				!= stream2->timing.v_front_porch)
5778582aea2SDavid Galiffi 		return false;
5788582aea2SDavid Galiffi 
579380604e2SKen Chalmers 	if (stream1->timing.pix_clk_100hz
580380604e2SKen Chalmers 				!= stream2->timing.pix_clk_100hz)
5814562236bSHarry Wentland 		return false;
5824562236bSHarry Wentland 
5833e27e10eSMikita Lipski 	if (stream1->clamping.c_depth != stream2->clamping.c_depth)
5843e27e10eSMikita Lipski 		return false;
5853e27e10eSMikita Lipski 
5864562236bSHarry Wentland 	if (stream1->phy_pix_clk != stream2->phy_pix_clk
5877e2fe319SCharlene Liu 			&& (!dc_is_dp_signal(stream1->signal)
5887e2fe319SCharlene Liu 			|| !dc_is_dp_signal(stream2->signal)))
5894562236bSHarry Wentland 		return false;
5904562236bSHarry Wentland 
591d77f778eSCharlene Liu 	if (stream1->view_format != stream2->view_format)
592d77f778eSCharlene Liu 		return false;
593d77f778eSCharlene Liu 
5940460f9abSJun Lei 	if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param)
5950460f9abSJun Lei 		return false;
5960460f9abSJun Lei 
5974562236bSHarry Wentland 	return true;
5984562236bSHarry Wentland }
is_dp_and_hdmi_sharable(struct dc_stream_state * stream1,struct dc_stream_state * stream2)5993e27e10eSMikita Lipski static bool is_dp_and_hdmi_sharable(
6003e27e10eSMikita Lipski 		struct dc_stream_state *stream1,
6013e27e10eSMikita Lipski 		struct dc_stream_state *stream2)
6023e27e10eSMikita Lipski {
6033e27e10eSMikita Lipski 	if (stream1->ctx->dc->caps.disable_dp_clk_share)
6043e27e10eSMikita Lipski 		return false;
6053e27e10eSMikita Lipski 
6063e27e10eSMikita Lipski 	if (stream1->clamping.c_depth != COLOR_DEPTH_888 ||
6073e27e10eSMikita Lipski 		stream2->clamping.c_depth != COLOR_DEPTH_888)
6083e27e10eSMikita Lipski 		return false;
6093e27e10eSMikita Lipski 
6103e27e10eSMikita Lipski 	return true;
6113e27e10eSMikita Lipski 
6123e27e10eSMikita Lipski }
6134562236bSHarry Wentland 
is_sharable_clk_src(const struct pipe_ctx * pipe_with_clk_src,const struct pipe_ctx * pipe)6144562236bSHarry Wentland static bool is_sharable_clk_src(
6154562236bSHarry Wentland 	const struct pipe_ctx *pipe_with_clk_src,
6164562236bSHarry Wentland 	const struct pipe_ctx *pipe)
6174562236bSHarry Wentland {
6184562236bSHarry Wentland 	if (pipe_with_clk_src->clock_source == NULL)
6194562236bSHarry Wentland 		return false;
6204562236bSHarry Wentland 
6214562236bSHarry Wentland 	if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
6224562236bSHarry Wentland 		return false;
6234562236bSHarry Wentland 
6243e27e10eSMikita Lipski 	if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) ||
6253e27e10eSMikita Lipski 		(dc_is_dp_signal(pipe->stream->signal) &&
6263e27e10eSMikita Lipski 		!is_dp_and_hdmi_sharable(pipe_with_clk_src->stream,
6273e27e10eSMikita Lipski 				     pipe->stream)))
6284562236bSHarry Wentland 		return false;
6294562236bSHarry Wentland 
6304562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
631fc69009eSMikita Lipski 			&& dc_is_dual_link_signal(pipe->stream->signal))
6324562236bSHarry Wentland 		return false;
6334562236bSHarry Wentland 
6344562236bSHarry Wentland 	if (dc_is_hdmi_signal(pipe->stream->signal)
635fc69009eSMikita Lipski 			&& dc_is_dual_link_signal(pipe_with_clk_src->stream->signal))
6364562236bSHarry Wentland 		return false;
6374562236bSHarry Wentland 
6384562236bSHarry Wentland 	if (!resource_are_streams_timing_synchronizable(
6394562236bSHarry Wentland 			pipe_with_clk_src->stream, pipe->stream))
6404562236bSHarry Wentland 		return false;
6414562236bSHarry Wentland 
6424562236bSHarry Wentland 	return true;
6434562236bSHarry Wentland }
6444562236bSHarry Wentland 
resource_find_used_clk_src_for_sharing(struct resource_context * res_ctx,struct pipe_ctx * pipe_ctx)6454562236bSHarry Wentland struct clock_source *resource_find_used_clk_src_for_sharing(
6464562236bSHarry Wentland 					struct resource_context *res_ctx,
6474562236bSHarry Wentland 					struct pipe_ctx *pipe_ctx)
6484562236bSHarry Wentland {
6494562236bSHarry Wentland 	int i;
6504562236bSHarry Wentland 
6514562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
6524562236bSHarry Wentland 		if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
6534562236bSHarry Wentland 			return res_ctx->pipe_ctx[i].clock_source;
6544562236bSHarry Wentland 	}
6554562236bSHarry Wentland 
6564562236bSHarry Wentland 	return NULL;
6574562236bSHarry Wentland }
6584562236bSHarry Wentland 
convert_pixel_format_to_dalsurface(enum surface_pixel_format surface_pixel_format)6594562236bSHarry Wentland static enum pixel_format convert_pixel_format_to_dalsurface(
6604562236bSHarry Wentland 		enum surface_pixel_format surface_pixel_format)
6614562236bSHarry Wentland {
6624562236bSHarry Wentland 	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
6634562236bSHarry Wentland 
6644562236bSHarry Wentland 	switch (surface_pixel_format) {
6654562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
6664562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_INDEX8;
6674562236bSHarry Wentland 		break;
6684562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
6694562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
6704562236bSHarry Wentland 		break;
6714562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
6724562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_RGB565;
6734562236bSHarry Wentland 		break;
6744562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
6754562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
6764562236bSHarry Wentland 		break;
6778693049aSTony Cheng 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
6784562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
6794562236bSHarry Wentland 		break;
6804562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
6814562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
6824562236bSHarry Wentland 		break;
6834562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
6844562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
6854562236bSHarry Wentland 		break;
6864562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
6874562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
6884562236bSHarry Wentland 		break;
6894562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
6904562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
6914562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_FP16;
6924562236bSHarry Wentland 		break;
6934562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
6944562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
69587449a90SAnthony Koo 		dal_pixel_format = PIXEL_FORMAT_420BPP8;
6964562236bSHarry Wentland 		break;
697ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
698ffbcd19aSVitaly Prosyak 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
69987449a90SAnthony Koo 		dal_pixel_format = PIXEL_FORMAT_420BPP10;
700ffbcd19aSVitaly Prosyak 		break;
7014562236bSHarry Wentland 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
702050cd3d6SMario Kleiner 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
7034562236bSHarry Wentland 	default:
7044562236bSHarry Wentland 		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
7054562236bSHarry Wentland 		break;
7064562236bSHarry Wentland 	}
7074562236bSHarry Wentland 	return dal_pixel_format;
7084562236bSHarry Wentland }
7094562236bSHarry Wentland 
get_vp_scan_direction(enum dc_rotation_angle rotation,bool horizontal_mirror,bool * orthogonal_rotation,bool * flip_vert_scan_dir,bool * flip_horz_scan_dir)7109b6067c0SDmytro Laktyushkin static inline void get_vp_scan_direction(
7119b6067c0SDmytro Laktyushkin 	enum dc_rotation_angle rotation,
7129b6067c0SDmytro Laktyushkin 	bool horizontal_mirror,
7139b6067c0SDmytro Laktyushkin 	bool *orthogonal_rotation,
7149b6067c0SDmytro Laktyushkin 	bool *flip_vert_scan_dir,
7159b6067c0SDmytro Laktyushkin 	bool *flip_horz_scan_dir)
7164562236bSHarry Wentland {
7179b6067c0SDmytro Laktyushkin 	*orthogonal_rotation = false;
7189b6067c0SDmytro Laktyushkin 	*flip_vert_scan_dir = false;
7199b6067c0SDmytro Laktyushkin 	*flip_horz_scan_dir = false;
7209b6067c0SDmytro Laktyushkin 	if (rotation == ROTATION_ANGLE_180) {
7219b6067c0SDmytro Laktyushkin 		*flip_vert_scan_dir = true;
7229b6067c0SDmytro Laktyushkin 		*flip_horz_scan_dir = true;
7239b6067c0SDmytro Laktyushkin 	} else if (rotation == ROTATION_ANGLE_90) {
7249b6067c0SDmytro Laktyushkin 		*orthogonal_rotation = true;
7259b6067c0SDmytro Laktyushkin 		*flip_horz_scan_dir = true;
7269b6067c0SDmytro Laktyushkin 	} else if (rotation == ROTATION_ANGLE_270) {
7279b6067c0SDmytro Laktyushkin 		*orthogonal_rotation = true;
7289b6067c0SDmytro Laktyushkin 		*flip_vert_scan_dir = true;
7299b6067c0SDmytro Laktyushkin 	}
7309b6067c0SDmytro Laktyushkin 
7319b6067c0SDmytro Laktyushkin 	if (horizontal_mirror)
7329b6067c0SDmytro Laktyushkin 		*flip_horz_scan_dir = !*flip_horz_scan_dir;
7334562236bSHarry Wentland }
7344562236bSHarry Wentland 
resource_get_num_mpc_splits(const struct pipe_ctx * pipe)73553f32880SWenjing Liu int resource_get_num_mpc_splits(const struct pipe_ctx *pipe)
736570bc18cSDmytro Laktyushkin {
737570bc18cSDmytro Laktyushkin 	int mpc_split_count = 0;
73853f32880SWenjing Liu 	const struct pipe_ctx *other_pipe = pipe->bottom_pipe;
739570bc18cSDmytro Laktyushkin 
740570bc18cSDmytro Laktyushkin 	while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
741570bc18cSDmytro Laktyushkin 		mpc_split_count++;
742570bc18cSDmytro Laktyushkin 		other_pipe = other_pipe->bottom_pipe;
743570bc18cSDmytro Laktyushkin 	}
744570bc18cSDmytro Laktyushkin 	other_pipe = pipe->top_pipe;
745570bc18cSDmytro Laktyushkin 	while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
746570bc18cSDmytro Laktyushkin 		mpc_split_count++;
747570bc18cSDmytro Laktyushkin 		other_pipe = other_pipe->top_pipe;
748570bc18cSDmytro Laktyushkin 	}
749570bc18cSDmytro Laktyushkin 
750570bc18cSDmytro Laktyushkin 	return mpc_split_count;
751570bc18cSDmytro Laktyushkin }
752570bc18cSDmytro Laktyushkin 
resource_get_num_odm_splits(const struct pipe_ctx * pipe)75353f32880SWenjing Liu int resource_get_num_odm_splits(const struct pipe_ctx *pipe)
754228a10d4SAlex Deucher {
755228a10d4SAlex Deucher 	int odm_split_count = 0;
7560f3b9542SWenjing Liu 
75753f32880SWenjing Liu 	pipe = resource_get_otg_master(pipe);
7580f3b9542SWenjing Liu 
75953f32880SWenjing Liu 	while (pipe->next_odm_pipe) {
760228a10d4SAlex Deucher 		odm_split_count++;
76153f32880SWenjing Liu 		pipe = pipe->next_odm_pipe;
762228a10d4SAlex Deucher 	}
763228a10d4SAlex Deucher 	return odm_split_count;
764228a10d4SAlex Deucher }
765228a10d4SAlex Deucher 
get_odm_split_index(struct pipe_ctx * pipe_ctx)7660f3b9542SWenjing Liu static int get_odm_split_index(struct pipe_ctx *pipe_ctx)
7675bf24270SDmytro Laktyushkin {
7680f3b9542SWenjing Liu 	int index = 0;
7695bf24270SDmytro Laktyushkin 
77053f32880SWenjing Liu 	pipe_ctx = resource_get_opp_head(pipe_ctx);
77153f32880SWenjing Liu 	if (!pipe_ctx)
77253f32880SWenjing Liu 		return 0;
7730f3b9542SWenjing Liu 
77453f32880SWenjing Liu 	while (pipe_ctx->prev_odm_pipe) {
7750f3b9542SWenjing Liu 		index++;
77653f32880SWenjing Liu 		pipe_ctx = pipe_ctx->prev_odm_pipe;
7770f3b9542SWenjing Liu 	}
7780f3b9542SWenjing Liu 
7790f3b9542SWenjing Liu 	return index;
7800f3b9542SWenjing Liu }
7810f3b9542SWenjing Liu 
get_mpc_split_index(struct pipe_ctx * pipe_ctx)7820f3b9542SWenjing Liu static int get_mpc_split_index(struct pipe_ctx *pipe_ctx)
7830f3b9542SWenjing Liu {
7840f3b9542SWenjing Liu 	struct pipe_ctx *split_pipe = pipe_ctx->top_pipe;
7850f3b9542SWenjing Liu 	int index = 0;
7860f3b9542SWenjing Liu 
7875bf24270SDmytro Laktyushkin 	while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) {
7880f3b9542SWenjing Liu 		index++;
7895bf24270SDmytro Laktyushkin 		split_pipe = split_pipe->top_pipe;
7905bf24270SDmytro Laktyushkin 	}
7919dfc3ee1SSamson Tam 
7920f3b9542SWenjing Liu 	return index;
7935bf24270SDmytro Laktyushkin }
7945bf24270SDmytro Laktyushkin 
7959b6067c0SDmytro Laktyushkin /*
7966566cae7SDmytro Laktyushkin  * This is a preliminary vp size calculation to allow us to check taps support.
7976566cae7SDmytro Laktyushkin  * The result is completely overridden afterwards.
7989b6067c0SDmytro Laktyushkin  */
calculate_viewport_size(struct pipe_ctx * pipe_ctx)7996566cae7SDmytro Laktyushkin static void calculate_viewport_size(struct pipe_ctx *pipe_ctx)
8006566cae7SDmytro Laktyushkin {
8016566cae7SDmytro Laktyushkin 	struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
8029b6067c0SDmytro Laktyushkin 
8036566cae7SDmytro Laktyushkin 	data->viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz, data->recout.width));
8046566cae7SDmytro Laktyushkin 	data->viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert, data->recout.height));
8056566cae7SDmytro Laktyushkin 	data->viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz_c, data->recout.width));
8066566cae7SDmytro Laktyushkin 	data->viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert_c, data->recout.height));
8076566cae7SDmytro Laktyushkin 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
8086566cae7SDmytro Laktyushkin 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
8096566cae7SDmytro Laktyushkin 		swap(data->viewport.width, data->viewport.height);
8106566cae7SDmytro Laktyushkin 		swap(data->viewport_c.width, data->viewport_c.height);
8119b6067c0SDmytro Laktyushkin 	}
812b2d0a103SDmytro Laktyushkin }
8131fbd2cfcSDmytro Laktyushkin 
intersect_rec(const struct rect * r0,const struct rect * r1)8140f3b9542SWenjing Liu static struct rect intersect_rec(const struct rect *r0, const struct rect *r1)
8154562236bSHarry Wentland {
8160f3b9542SWenjing Liu 	struct rect rec;
8170f3b9542SWenjing Liu 	int r0_x_end = r0->x + r0->width;
8180f3b9542SWenjing Liu 	int r1_x_end = r1->x + r1->width;
8190f3b9542SWenjing Liu 	int r0_y_end = r0->y + r0->height;
8200f3b9542SWenjing Liu 	int r1_y_end = r1->y + r1->height;
8210f3b9542SWenjing Liu 
8220f3b9542SWenjing Liu 	rec.x = r0->x > r1->x ? r0->x : r1->x;
8230f3b9542SWenjing Liu 	rec.width = r0_x_end > r1_x_end ? r1_x_end - rec.x : r0_x_end - rec.x;
8240f3b9542SWenjing Liu 	rec.y = r0->y > r1->y ? r0->y : r1->y;
8250f3b9542SWenjing Liu 	rec.height = r0_y_end > r1_y_end ? r1_y_end - rec.y : r0_y_end - rec.y;
8260f3b9542SWenjing Liu 
8270f3b9542SWenjing Liu 	/* in case that there is no intersection */
8280f3b9542SWenjing Liu 	if (rec.width < 0 || rec.height < 0)
8290f3b9542SWenjing Liu 		memset(&rec, 0, sizeof(rec));
8300f3b9542SWenjing Liu 
8310f3b9542SWenjing Liu 	return rec;
8320f3b9542SWenjing Liu }
8330f3b9542SWenjing Liu 
shift_rec(const struct rect * rec_in,int x,int y)8340f3b9542SWenjing Liu static struct rect shift_rec(const struct rect *rec_in, int x, int y)
8350f3b9542SWenjing Liu {
8360f3b9542SWenjing Liu 	struct rect rec_out = *rec_in;
8370f3b9542SWenjing Liu 
8380f3b9542SWenjing Liu 	rec_out.x += x;
8390f3b9542SWenjing Liu 	rec_out.y += y;
8400f3b9542SWenjing Liu 
8410f3b9542SWenjing Liu 	return rec_out;
8420f3b9542SWenjing Liu }
8430f3b9542SWenjing Liu 
calculate_odm_slice_in_timing_active(struct pipe_ctx * pipe_ctx)8440f3b9542SWenjing Liu static struct rect calculate_odm_slice_in_timing_active(struct pipe_ctx *pipe_ctx)
8450f3b9542SWenjing Liu {
8460971c40eSHarry Wentland 	const struct dc_stream_state *stream = pipe_ctx->stream;
84753f32880SWenjing Liu 	int odm_slice_count = resource_get_num_odm_splits(pipe_ctx) + 1;
8480f3b9542SWenjing Liu 	int odm_slice_idx = get_odm_split_index(pipe_ctx);
8490f3b9542SWenjing Liu 	bool is_last_odm_slice = (odm_slice_idx + 1) == odm_slice_count;
8500f3b9542SWenjing Liu 	int h_active = stream->timing.h_addressable +
8510f3b9542SWenjing Liu 			stream->timing.h_border_left +
8520f3b9542SWenjing Liu 			stream->timing.h_border_right;
8530f3b9542SWenjing Liu 	int odm_slice_width = h_active / odm_slice_count;
8540f3b9542SWenjing Liu 	struct rect odm_rec;
8554562236bSHarry Wentland 
8560f3b9542SWenjing Liu 	odm_rec.x = odm_slice_width * odm_slice_idx;
8570f3b9542SWenjing Liu 	odm_rec.width = is_last_odm_slice ?
8580f3b9542SWenjing Liu 			/* last slice width is the reminder of h_active */
8590f3b9542SWenjing Liu 			h_active - odm_slice_width * (odm_slice_count - 1) :
8600f3b9542SWenjing Liu 			/* odm slice width is the floor of h_active / count */
8610f3b9542SWenjing Liu 			odm_slice_width;
8620f3b9542SWenjing Liu 	odm_rec.y = 0;
8630f3b9542SWenjing Liu 	odm_rec.height = stream->timing.v_addressable +
8640f3b9542SWenjing Liu 			stream->timing.v_border_bottom +
8650f3b9542SWenjing Liu 			stream->timing.v_border_top;
8665bf24270SDmytro Laktyushkin 
8670f3b9542SWenjing Liu 	return odm_rec;
8680f3b9542SWenjing Liu }
8690f3b9542SWenjing Liu 
calculate_plane_rec_in_timing_active(struct pipe_ctx * pipe_ctx,const struct rect * rec_in)8700f3b9542SWenjing Liu static struct rect calculate_plane_rec_in_timing_active(
8710f3b9542SWenjing Liu 		struct pipe_ctx *pipe_ctx,
8720f3b9542SWenjing Liu 		const struct rect *rec_in)
8730f3b9542SWenjing Liu {
87405e3d830SWesley Chalmers 	/*
8750f3b9542SWenjing Liu 	 * The following diagram shows an example where we map a 1920x1200
8760f3b9542SWenjing Liu 	 * desktop to a 2560x1440 timing with a plane rect in the middle
8770f3b9542SWenjing Liu 	 * of the screen. To map a plane rect from Stream Source to Timing
8780f3b9542SWenjing Liu 	 * Active space, we first multiply stream scaling ratios (i.e 2304/1920
8790f3b9542SWenjing Liu 	 * horizontal and 1440/1200 vertical) to the plane's x and y, then
8800f3b9542SWenjing Liu 	 * we add stream destination offsets (i.e 128 horizontal, 0 vertical).
8810f3b9542SWenjing Liu 	 * This will give us a plane rect's position in Timing Active. However
8820f3b9542SWenjing Liu 	 * we have to remove the fractional. The rule is that we find left/right
8830f3b9542SWenjing Liu 	 * and top/bottom positions and round the value to the adjacent integer.
8840f3b9542SWenjing Liu 	 *
8850f3b9542SWenjing Liu 	 * Stream Source Space
8860f3b9542SWenjing Liu 	 * ------------
8870f3b9542SWenjing Liu 	 *        __________________________________________________
8880f3b9542SWenjing Liu 	 *       |Stream Source (1920 x 1200) ^                     |
8890f3b9542SWenjing Liu 	 *       |                            y                     |
8900f3b9542SWenjing Liu 	 *       |         <------- w --------|>                    |
8910f3b9542SWenjing Liu 	 *       |          __________________V                     |
8920f3b9542SWenjing Liu 	 *       |<-- x -->|Plane//////////////| ^                  |
8930f3b9542SWenjing Liu 	 *       |         |(pre scale)////////| |                  |
8940f3b9542SWenjing Liu 	 *       |         |///////////////////| |                  |
8950f3b9542SWenjing Liu 	 *       |         |///////////////////| h                  |
8960f3b9542SWenjing Liu 	 *       |         |///////////////////| |                  |
8970f3b9542SWenjing Liu 	 *       |         |///////////////////| |                  |
8980f3b9542SWenjing Liu 	 *       |         |///////////////////| V                  |
8990f3b9542SWenjing Liu 	 *       |                                                  |
9000f3b9542SWenjing Liu 	 *       |                                                  |
9010f3b9542SWenjing Liu 	 *       |__________________________________________________|
9020f3b9542SWenjing Liu 	 *
9030f3b9542SWenjing Liu 	 *
9040f3b9542SWenjing Liu 	 * Timing Active Space
9050f3b9542SWenjing Liu 	 * ---------------------------------
9060f3b9542SWenjing Liu 	 *
9070f3b9542SWenjing Liu 	 *       Timing Active (2560 x 1440)
9080f3b9542SWenjing Liu 	 *        __________________________________________________
9090f3b9542SWenjing Liu 	 *       |*****|  Stteam Destination (2304 x 1440)    |*****|
9100f3b9542SWenjing Liu 	 *       |*****|                                      |*****|
9110f3b9542SWenjing Liu 	 *       |<128>|                                      |*****|
9120f3b9542SWenjing Liu 	 *       |*****|     __________________               |*****|
9130f3b9542SWenjing Liu 	 *       |*****|    |Plane/////////////|              |*****|
9140f3b9542SWenjing Liu 	 *       |*****|    |(post scale)//////|              |*****|
9150f3b9542SWenjing Liu 	 *       |*****|    |//////////////////|              |*****|
9160f3b9542SWenjing Liu 	 *       |*****|    |//////////////////|              |*****|
9170f3b9542SWenjing Liu 	 *       |*****|    |//////////////////|              |*****|
9180f3b9542SWenjing Liu 	 *       |*****|    |//////////////////|              |*****|
9190f3b9542SWenjing Liu 	 *       |*****|                                      |*****|
9200f3b9542SWenjing Liu 	 *       |*****|                                      |*****|
9210f3b9542SWenjing Liu 	 *       |*****|                                      |*****|
9220f3b9542SWenjing Liu 	 *       |*****|______________________________________|*****|
9230f3b9542SWenjing Liu 	 *
9240f3b9542SWenjing Liu 	 * So the resulting formulas are shown below:
9250f3b9542SWenjing Liu 	 *
9260f3b9542SWenjing Liu 	 * recout_x = 128 + round(plane_x * 2304 / 1920)
9270f3b9542SWenjing Liu 	 * recout_w = 128 + round((plane_x + plane_w) * 2304 / 1920) - recout_x
9280f3b9542SWenjing Liu 	 * recout_y = 0 + round(plane_y * 1440 / 1280)
9290f3b9542SWenjing Liu 	 * recout_h = 0 + round((plane_y + plane_h) * 1440 / 1200) - recout_y
9300f3b9542SWenjing Liu 	 *
9310f3b9542SWenjing Liu 	 * NOTE: fixed point division is not error free. To reduce errors
9320f3b9542SWenjing Liu 	 * introduced by fixed point division, we divide only after
9330f3b9542SWenjing Liu 	 * multiplication is complete.
93405e3d830SWesley Chalmers 	 */
9350f3b9542SWenjing Liu 	const struct dc_stream_state *stream = pipe_ctx->stream;
9360f3b9542SWenjing Liu 	struct rect rec_out = {0};
9370f3b9542SWenjing Liu 	struct fixed31_32 temp;
93825b31581SWesley Chalmers 
9390f3b9542SWenjing Liu 	temp = dc_fixpt_from_fraction(rec_in->x * stream->dst.width,
9400f3b9542SWenjing Liu 			stream->src.width);
9410f3b9542SWenjing Liu 	rec_out.x = stream->dst.x + dc_fixpt_round(temp);
9424562236bSHarry Wentland 
9430f3b9542SWenjing Liu 	temp = dc_fixpt_from_fraction(
9440f3b9542SWenjing Liu 			(rec_in->x + rec_in->width) * stream->dst.width,
9450f3b9542SWenjing Liu 			stream->src.width);
9460f3b9542SWenjing Liu 	rec_out.width = stream->dst.x + dc_fixpt_round(temp) - rec_out.x;
9474562236bSHarry Wentland 
9480f3b9542SWenjing Liu 	temp = dc_fixpt_from_fraction(rec_in->y * stream->dst.height,
9490f3b9542SWenjing Liu 			stream->src.height);
9500f3b9542SWenjing Liu 	rec_out.y = stream->dst.y + dc_fixpt_round(temp);
951b2d0a103SDmytro Laktyushkin 
9520f3b9542SWenjing Liu 	temp = dc_fixpt_from_fraction(
9530f3b9542SWenjing Liu 			(rec_in->y + rec_in->height) * stream->dst.height,
9540f3b9542SWenjing Liu 			stream->src.height);
9550f3b9542SWenjing Liu 	rec_out.height = stream->dst.y + dc_fixpt_round(temp) - rec_out.y;
9560f3b9542SWenjing Liu 
9570f3b9542SWenjing Liu 	return rec_out;
9580f3b9542SWenjing Liu }
9590f3b9542SWenjing Liu 
calculate_mpc_slice_in_timing_active(struct pipe_ctx * pipe_ctx,struct rect * plane_clip_rec)9600f3b9542SWenjing Liu static struct rect calculate_mpc_slice_in_timing_active(
9610f3b9542SWenjing Liu 		struct pipe_ctx *pipe_ctx,
9620f3b9542SWenjing Liu 		struct rect *plane_clip_rec)
9630f3b9542SWenjing Liu {
9640f3b9542SWenjing Liu 	const struct dc_stream_state *stream = pipe_ctx->stream;
96553f32880SWenjing Liu 	int mpc_slice_count = resource_get_num_mpc_splits(pipe_ctx) + 1;
9660f3b9542SWenjing Liu 	int mpc_slice_idx = get_mpc_split_index(pipe_ctx);
9670f3b9542SWenjing Liu 	int epimo = mpc_slice_count - plane_clip_rec->width % mpc_slice_count - 1;
9680f3b9542SWenjing Liu 	struct rect mpc_rec;
9690f3b9542SWenjing Liu 
9700f3b9542SWenjing Liu 	mpc_rec.width = plane_clip_rec->width / mpc_slice_count;
9710f3b9542SWenjing Liu 	mpc_rec.x = plane_clip_rec->x + mpc_rec.width * mpc_slice_idx;
9720f3b9542SWenjing Liu 	mpc_rec.height = plane_clip_rec->height;
9730f3b9542SWenjing Liu 	mpc_rec.y = plane_clip_rec->y;
9740f3b9542SWenjing Liu 	ASSERT(mpc_slice_count == 1 ||
9750f3b9542SWenjing Liu 			stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE ||
9760f3b9542SWenjing Liu 			mpc_rec.width % 2 == 0);
9770f3b9542SWenjing Liu 
9785bf24270SDmytro Laktyushkin 	/* extra pixels in the division remainder need to go to pipes after
9795bf24270SDmytro Laktyushkin 	 * the extra pixel index minus one(epimo) defined here as:
9805bf24270SDmytro Laktyushkin 	 */
9810f3b9542SWenjing Liu 	if (mpc_slice_idx > epimo) {
9820f3b9542SWenjing Liu 		mpc_rec.x += mpc_slice_idx - epimo - 1;
9830f3b9542SWenjing Liu 		mpc_rec.width += 1;
9845bf24270SDmytro Laktyushkin 	}
985bf27f5deSLeo Ma 
9860f3b9542SWenjing Liu 	if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
9870f3b9542SWenjing Liu 		ASSERT(mpc_rec.height % 2 == 0);
9880f3b9542SWenjing Liu 		mpc_rec.height /= 2;
9890f3b9542SWenjing Liu 	}
9900f3b9542SWenjing Liu 	return mpc_rec;
991bf27f5deSLeo Ma }
992bf27f5deSLeo Ma 
adjust_recout_for_visual_confirm(struct rect * recout,struct pipe_ctx * pipe_ctx)9930f3b9542SWenjing Liu static void adjust_recout_for_visual_confirm(struct rect *recout,
9940f3b9542SWenjing Liu 		struct pipe_ctx *pipe_ctx)
9950f3b9542SWenjing Liu {
9960f3b9542SWenjing Liu 	struct dc *dc = pipe_ctx->stream->ctx->dc;
9970f3b9542SWenjing Liu 	int dpp_offset, base_offset;
9980f3b9542SWenjing Liu 
999*17117871SGabe Teeger 	if (dc->debug.visual_confirm == VISUAL_CONFIRM_DISABLE || !pipe_ctx->plane_res.dpp)
10000f3b9542SWenjing Liu 		return;
10010f3b9542SWenjing Liu 
1002c5a4f901SWenjing Liu 	dpp_offset = pipe_ctx->stream->timing.v_addressable / VISUAL_CONFIRM_DPP_OFFSET_DENO;
1003c5a4f901SWenjing Liu 	dpp_offset *= pipe_ctx->plane_res.dpp->inst;
10040f3b9542SWenjing Liu 
10050f3b9542SWenjing Liu 	if ((dc->debug.visual_confirm_rect_height >= VISUAL_CONFIRM_BASE_MIN) &&
10060f3b9542SWenjing Liu 			dc->debug.visual_confirm_rect_height <= VISUAL_CONFIRM_BASE_MAX)
10070f3b9542SWenjing Liu 		base_offset = dc->debug.visual_confirm_rect_height;
10080f3b9542SWenjing Liu 	else
10090f3b9542SWenjing Liu 		base_offset = VISUAL_CONFIRM_BASE_DEFAULT;
10100f3b9542SWenjing Liu 
10110f3b9542SWenjing Liu 	recout->height -= base_offset;
10120f3b9542SWenjing Liu 	recout->height -= dpp_offset;
1013bf27f5deSLeo Ma }
10140f3b9542SWenjing Liu 
10150f3b9542SWenjing Liu /*
10160f3b9542SWenjing Liu  * The function maps a plane clip from Stream Source Space to ODM Slice Space
10170f3b9542SWenjing Liu  * and calculates the rec of the overlapping area of MPC slice of the plane
10180f3b9542SWenjing Liu  * clip, ODM slice associated with the pipe context and stream destination rec.
10190f3b9542SWenjing Liu  */
calculate_recout(struct pipe_ctx * pipe_ctx)10200f3b9542SWenjing Liu static void calculate_recout(struct pipe_ctx *pipe_ctx)
10210f3b9542SWenjing Liu {
10220f3b9542SWenjing Liu 	/*
10230f3b9542SWenjing Liu 	 * A plane clip represents the desired plane size and position in Stream
10240f3b9542SWenjing Liu 	 * Source Space. Stream Source is the destination where all planes are
10250f3b9542SWenjing Liu 	 * blended (i.e. positioned, scaled and overlaid). It is a canvas where
10260f3b9542SWenjing Liu 	 * all planes associated with the current stream are drawn together.
10270f3b9542SWenjing Liu 	 * After Stream Source is completed, we will further scale and
10280f3b9542SWenjing Liu 	 * reposition the entire canvas of the stream source to Stream
10290f3b9542SWenjing Liu 	 * Destination in Timing Active Space. This could be due to display
10300f3b9542SWenjing Liu 	 * overscan adjustment where we will need to rescale and reposition all
10310f3b9542SWenjing Liu 	 * the planes so they can fit into a TV with overscan or downscale
10320f3b9542SWenjing Liu 	 * upscale features such as GPU scaling or VSR.
10330f3b9542SWenjing Liu 	 *
10340f3b9542SWenjing Liu 	 * This two step blending is a virtual procedure in software. In
10350f3b9542SWenjing Liu 	 * hardware there is no such thing as Stream Source. all planes are
10360f3b9542SWenjing Liu 	 * blended once in Timing Active Space. Software virtualizes a Stream
10370f3b9542SWenjing Liu 	 * Source space to decouple the math complicity so scaling param
10380f3b9542SWenjing Liu 	 * calculation focuses on one step at a time.
10390f3b9542SWenjing Liu 	 *
10400f3b9542SWenjing Liu 	 * In the following two diagrams, user applied 10% overscan adjustment
10410f3b9542SWenjing Liu 	 * so the Stream Source needs to be scaled down a little before mapping
10420f3b9542SWenjing Liu 	 * to Timing Active Space. As a result the Plane Clip is also scaled
10430f3b9542SWenjing Liu 	 * down by the same ratio, Plane Clip position (i.e. x and y) with
10440f3b9542SWenjing Liu 	 * respect to Stream Source is also scaled down. To map it in Timing
10450f3b9542SWenjing Liu 	 * Active Space additional x and y offsets from Stream Destination are
10460f3b9542SWenjing Liu 	 * added to Plane Clip as well.
10470f3b9542SWenjing Liu 	 *
10480f3b9542SWenjing Liu 	 * Stream Source Space
10490f3b9542SWenjing Liu 	 * ------------
10500f3b9542SWenjing Liu 	 *        __________________________________________________
10510f3b9542SWenjing Liu 	 *       |Stream Source (3840 x 2160) ^                     |
10520f3b9542SWenjing Liu 	 *       |                            y                     |
10530f3b9542SWenjing Liu 	 *       |                            |                     |
10540f3b9542SWenjing Liu 	 *       |          __________________V                     |
10550f3b9542SWenjing Liu 	 *       |<-- x -->|Plane Clip/////////|                    |
10560f3b9542SWenjing Liu 	 *       |         |(pre scale)////////|                    |
10570f3b9542SWenjing Liu 	 *       |         |///////////////////|                    |
10580f3b9542SWenjing Liu 	 *       |         |///////////////////|                    |
10590f3b9542SWenjing Liu 	 *       |         |///////////////////|                    |
10600f3b9542SWenjing Liu 	 *       |         |///////////////////|                    |
10610f3b9542SWenjing Liu 	 *       |         |///////////////////|                    |
10620f3b9542SWenjing Liu 	 *       |                                                  |
10630f3b9542SWenjing Liu 	 *       |                                                  |
10640f3b9542SWenjing Liu 	 *       |__________________________________________________|
10650f3b9542SWenjing Liu 	 *
10660f3b9542SWenjing Liu 	 *
10670f3b9542SWenjing Liu 	 * Timing Active Space (3840 x 2160)
10680f3b9542SWenjing Liu 	 * ---------------------------------
10690f3b9542SWenjing Liu 	 *
10700f3b9542SWenjing Liu 	 *       Timing Active
10710f3b9542SWenjing Liu 	 *        __________________________________________________
10720f3b9542SWenjing Liu 	 *       | y_____________________________________________   |
10730f3b9542SWenjing Liu 	 *       |x |Stream Destination (3456 x 1944)            |  |
10740f3b9542SWenjing Liu 	 *       |  |                                            |  |
10750f3b9542SWenjing Liu 	 *       |  |        __________________                  |  |
10760f3b9542SWenjing Liu 	 *       |  |       |Plane Clip////////|                 |  |
10770f3b9542SWenjing Liu 	 *       |  |       |(post scale)//////|                 |  |
10780f3b9542SWenjing Liu 	 *       |  |       |//////////////////|                 |  |
10790f3b9542SWenjing Liu 	 *       |  |       |//////////////////|                 |  |
10800f3b9542SWenjing Liu 	 *       |  |       |//////////////////|                 |  |
10810f3b9542SWenjing Liu 	 *       |  |       |//////////////////|                 |  |
10820f3b9542SWenjing Liu 	 *       |  |                                            |  |
10830f3b9542SWenjing Liu 	 *       |  |                                            |  |
10840f3b9542SWenjing Liu 	 *       |  |____________________________________________|  |
10850f3b9542SWenjing Liu 	 *       |__________________________________________________|
10860f3b9542SWenjing Liu 	 *
10870f3b9542SWenjing Liu 	 *
10880f3b9542SWenjing Liu 	 * In Timing Active Space a plane clip could be further sliced into
10890f3b9542SWenjing Liu 	 * pieces called MPC slices. Each Pipe Context is responsible for
10900f3b9542SWenjing Liu 	 * processing only one MPC slice so the plane processing workload can be
10910f3b9542SWenjing Liu 	 * distributed to multiple DPP Pipes. MPC slices could be blended
10920f3b9542SWenjing Liu 	 * together to a single ODM slice. Each ODM slice is responsible for
10930f3b9542SWenjing Liu 	 * processing a portion of Timing Active divided horizontally so the
10940f3b9542SWenjing Liu 	 * output pixel processing workload can be distributed to multiple OPP
10950f3b9542SWenjing Liu 	 * pipes. All ODM slices are mapped together in ODM block so all MPC
10960f3b9542SWenjing Liu 	 * slices belong to different ODM slices could be pieced together to
10970f3b9542SWenjing Liu 	 * form a single image in Timing Active. MPC slices must belong to
10980f3b9542SWenjing Liu 	 * single ODM slice. If an MPC slice goes across ODM slice boundary, it
10990f3b9542SWenjing Liu 	 * needs to be divided into two MPC slices one for each ODM slice.
11000f3b9542SWenjing Liu 	 *
11010f3b9542SWenjing Liu 	 * In the following diagram the output pixel processing workload is
11020f3b9542SWenjing Liu 	 * divided horizontally into two ODM slices one for each OPP blend tree.
11030f3b9542SWenjing Liu 	 * OPP0 blend tree is responsible for processing left half of Timing
11040f3b9542SWenjing Liu 	 * Active, while OPP2 blend tree is responsible for processing right
11050f3b9542SWenjing Liu 	 * half.
11060f3b9542SWenjing Liu 	 *
11070f3b9542SWenjing Liu 	 * The plane has two MPC slices. However since the right MPC slice goes
11080f3b9542SWenjing Liu 	 * across ODM boundary, two DPP pipes are needed one for each OPP blend
11090f3b9542SWenjing Liu 	 * tree. (i.e. DPP1 for OPP0 blend tree and DPP2 for OPP2 blend tree).
11100f3b9542SWenjing Liu 	 *
11110f3b9542SWenjing Liu 	 * Assuming that we have a Pipe Context associated with OPP0 and DPP1
11120f3b9542SWenjing Liu 	 * working on processing the plane in the diagram. We want to know the
11130f3b9542SWenjing Liu 	 * width and height of the shaded rectangle and its relative position
11140f3b9542SWenjing Liu 	 * with respect to the ODM slice0. This is called the recout of the pipe
11150f3b9542SWenjing Liu 	 * context.
11160f3b9542SWenjing Liu 	 *
11170f3b9542SWenjing Liu 	 * Planes can be at arbitrary size and position and there could be an
11180f3b9542SWenjing Liu 	 * arbitrary number of MPC and ODM slices. The algorithm needs to take
11190f3b9542SWenjing Liu 	 * all scenarios into account.
11200f3b9542SWenjing Liu 	 *
11210f3b9542SWenjing Liu 	 * Timing Active Space (3840 x 2160)
11220f3b9542SWenjing Liu 	 * ---------------------------------
11230f3b9542SWenjing Liu 	 *
11240f3b9542SWenjing Liu 	 *       Timing Active
11250f3b9542SWenjing Liu 	 *        __________________________________________________
11260f3b9542SWenjing Liu 	 *       |OPP0(ODM slice0)^        |OPP2(ODM slice1)        |
11270f3b9542SWenjing Liu 	 *       |                y        |                        |
11280f3b9542SWenjing Liu 	 *       |                |  <- w ->                        |
11290f3b9542SWenjing Liu 	 *       |           _____V________|____                    |
11300f3b9542SWenjing Liu 	 *       |          |DPP0 ^  |DPP1 |DPP2|                   |
11310f3b9542SWenjing Liu 	 *       |<------ x |-----|->|/////|    |                   |
11320f3b9542SWenjing Liu 	 *       |          |     |  |/////|    |                   |
11330f3b9542SWenjing Liu 	 *       |          |     h  |/////|    |                   |
11340f3b9542SWenjing Liu 	 *       |          |     |  |/////|    |                   |
11350f3b9542SWenjing Liu 	 *       |          |_____V__|/////|____|                   |
11360f3b9542SWenjing Liu 	 *       |                         |                        |
11370f3b9542SWenjing Liu 	 *       |                         |                        |
11380f3b9542SWenjing Liu 	 *       |                         |                        |
11390f3b9542SWenjing Liu 	 *       |_________________________|________________________|
11400f3b9542SWenjing Liu 	 *
11410f3b9542SWenjing Liu 	 *
11420f3b9542SWenjing Liu 	 */
11430f3b9542SWenjing Liu 	struct rect plane_clip;
11440f3b9542SWenjing Liu 	struct rect mpc_slice_of_plane_clip;
11450f3b9542SWenjing Liu 	struct rect odm_slice;
11460f3b9542SWenjing Liu 	struct rect overlapping_area;
11470f3b9542SWenjing Liu 
11480f3b9542SWenjing Liu 	plane_clip = calculate_plane_rec_in_timing_active(pipe_ctx,
11490f3b9542SWenjing Liu 			&pipe_ctx->plane_state->clip_rect);
11500f3b9542SWenjing Liu 	/* guard plane clip from drawing beyond stream dst here */
11510f3b9542SWenjing Liu 	plane_clip = intersect_rec(&plane_clip,
11520f3b9542SWenjing Liu 				&pipe_ctx->stream->dst);
11530f3b9542SWenjing Liu 	mpc_slice_of_plane_clip = calculate_mpc_slice_in_timing_active(
11540f3b9542SWenjing Liu 			pipe_ctx, &plane_clip);
11550f3b9542SWenjing Liu 	odm_slice = calculate_odm_slice_in_timing_active(pipe_ctx);
11560f3b9542SWenjing Liu 	overlapping_area = intersect_rec(&mpc_slice_of_plane_clip, &odm_slice);
1157e75b965eSWenjing Liu 	if (overlapping_area.height > 0 &&
1158e75b965eSWenjing Liu 			overlapping_area.width > 0) {
1159e75b965eSWenjing Liu 		/* shift the overlapping area so it is with respect to current
1160e75b965eSWenjing Liu 		 * ODM slice's position
11610f3b9542SWenjing Liu 		 */
11620f3b9542SWenjing Liu 		pipe_ctx->plane_res.scl_data.recout = shift_rec(
11630f3b9542SWenjing Liu 				&overlapping_area,
11640f3b9542SWenjing Liu 				-odm_slice.x, -odm_slice.y);
1165e75b965eSWenjing Liu 		adjust_recout_for_visual_confirm(
1166e75b965eSWenjing Liu 				&pipe_ctx->plane_res.scl_data.recout,
11670f3b9542SWenjing Liu 				pipe_ctx);
1168e75b965eSWenjing Liu 	} else {
1169e75b965eSWenjing Liu 		/* if there is no overlap, zero recout */
1170e75b965eSWenjing Liu 		memset(&pipe_ctx->plane_res.scl_data.recout, 0,
1171e75b965eSWenjing Liu 				sizeof(struct rect));
1172e75b965eSWenjing Liu 	}
1173e75b965eSWenjing Liu 
11744562236bSHarry Wentland }
1175b2d0a103SDmytro Laktyushkin 
calculate_scaling_ratios(struct pipe_ctx * pipe_ctx)1176b2d0a103SDmytro Laktyushkin static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
11774562236bSHarry Wentland {
11783be5262eSHarry Wentland 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
11790971c40eSHarry Wentland 	const struct dc_stream_state *stream = pipe_ctx->stream;
11803be5262eSHarry Wentland 	struct rect surf_src = plane_state->src_rect;
11814fa086b9SLeo (Sunpeng) Li 	const int in_w = stream->src.width;
11824fa086b9SLeo (Sunpeng) Li 	const int in_h = stream->src.height;
11834fa086b9SLeo (Sunpeng) Li 	const int out_w = stream->dst.width;
11844fa086b9SLeo (Sunpeng) Li 	const int out_h = stream->dst.height;
11854562236bSHarry Wentland 
11869b6067c0SDmytro Laktyushkin 	/*Swap surf_src height and width since scaling ratios are in recout rotation*/
11873be5262eSHarry Wentland 	if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
11883be5262eSHarry Wentland 			pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
11899b6067c0SDmytro Laktyushkin 		swap(surf_src.height, surf_src.width);
119086006a7fSDmytro Laktyushkin 
1191eb0e5154SDmytro Laktyushkin 	pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction(
119286006a7fSDmytro Laktyushkin 					surf_src.width,
11933be5262eSHarry Wentland 					plane_state->dst_rect.width);
1194eb0e5154SDmytro Laktyushkin 	pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction(
119586006a7fSDmytro Laktyushkin 					surf_src.height,
11963be5262eSHarry Wentland 					plane_state->dst_rect.height);
11974562236bSHarry Wentland 
11984fa086b9SLeo (Sunpeng) Li 	if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
11996702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2;
12004fa086b9SLeo (Sunpeng) Li 	else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
12016702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2;
12024562236bSHarry Wentland 
12036702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64(
12046702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h);
12056702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64(
12066702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w);
12074562236bSHarry Wentland 
12086702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz;
12096702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert;
12104562236bSHarry Wentland 
12116702a9acSHarry Wentland 	if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8
12126702a9acSHarry Wentland 			|| pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) {
12136702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2;
12146702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2;
12154562236bSHarry Wentland 	}
12160002d3acSDmytro Laktyushkin 	pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate(
12170002d3acSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.ratios.horz, 19);
12180002d3acSDmytro Laktyushkin 	pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate(
12190002d3acSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.ratios.vert, 19);
12200002d3acSDmytro Laktyushkin 	pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate(
12210002d3acSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.ratios.horz_c, 19);
12220002d3acSDmytro Laktyushkin 	pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate(
12230002d3acSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.ratios.vert_c, 19);
12244562236bSHarry Wentland }
12254562236bSHarry Wentland 
12266566cae7SDmytro Laktyushkin 
12276566cae7SDmytro Laktyushkin /*
12286566cae7SDmytro Laktyushkin  * We completely calculate vp offset, size and inits here based entirely on scaling
12296566cae7SDmytro Laktyushkin  * ratios and recout for pixel perfect pipe combine.
12306566cae7SDmytro Laktyushkin  */
calculate_init_and_vp(bool flip_scan_dir,int recout_offset_within_recout_full,int recout_size,int src_size,int taps,struct fixed31_32 ratio,struct fixed31_32 * init,int * vp_offset,int * vp_size)12316566cae7SDmytro Laktyushkin static void calculate_init_and_vp(
12329b6067c0SDmytro Laktyushkin 		bool flip_scan_dir,
12336566cae7SDmytro Laktyushkin 		int recout_offset_within_recout_full,
12346566cae7SDmytro Laktyushkin 		int recout_size,
12359b6067c0SDmytro Laktyushkin 		int src_size,
12369b6067c0SDmytro Laktyushkin 		int taps,
12379b6067c0SDmytro Laktyushkin 		struct fixed31_32 ratio,
12389b6067c0SDmytro Laktyushkin 		struct fixed31_32 *init,
12399b6067c0SDmytro Laktyushkin 		int *vp_offset,
12409b6067c0SDmytro Laktyushkin 		int *vp_size)
12414562236bSHarry Wentland {
12426566cae7SDmytro Laktyushkin 	struct fixed31_32 temp;
12439b6067c0SDmytro Laktyushkin 	int int_part;
12449b6067c0SDmytro Laktyushkin 
12456566cae7SDmytro Laktyushkin 	/*
12466566cae7SDmytro Laktyushkin 	 * First of the taps starts sampling pixel number <init_int_part> corresponding to recout
12476566cae7SDmytro Laktyushkin 	 * pixel 1. Next recout pixel samples int part of <init + scaling ratio> and so on.
12486566cae7SDmytro Laktyushkin 	 * All following calculations are based on this logic.
12496566cae7SDmytro Laktyushkin 	 *
12506566cae7SDmytro Laktyushkin 	 * Init calculated according to formula:
12516566cae7SDmytro Laktyushkin 	 * 	init = (scaling_ratio + number_of_taps + 1) / 2
12526566cae7SDmytro Laktyushkin 	 * 	init_bot = init + scaling_ratio
12536566cae7SDmytro Laktyushkin 	 * 	to get pixel perfect combine add the fraction from calculating vp offset
12546566cae7SDmytro Laktyushkin 	 */
12556566cae7SDmytro Laktyushkin 	temp = dc_fixpt_mul_int(ratio, recout_offset_within_recout_full);
12566566cae7SDmytro Laktyushkin 	*vp_offset = dc_fixpt_floor(temp);
12576566cae7SDmytro Laktyushkin 	temp.value &= 0xffffffff;
12586566cae7SDmytro Laktyushkin 	*init = dc_fixpt_truncate(dc_fixpt_add(dc_fixpt_div_int(
12596566cae7SDmytro Laktyushkin 			dc_fixpt_add_int(ratio, taps + 1), 2), temp), 19);
12606566cae7SDmytro Laktyushkin 	/*
12616566cae7SDmytro Laktyushkin 	 * If viewport has non 0 offset and there are more taps than covered by init then
12626566cae7SDmytro Laktyushkin 	 * we should decrease the offset and increase init so we are never sampling
12636566cae7SDmytro Laktyushkin 	 * outside of viewport.
12646566cae7SDmytro Laktyushkin 	 */
12656566cae7SDmytro Laktyushkin 	int_part = dc_fixpt_floor(*init);
12669b6067c0SDmytro Laktyushkin 	if (int_part < taps) {
12676566cae7SDmytro Laktyushkin 		int_part = taps - int_part;
12686566cae7SDmytro Laktyushkin 		if (int_part > *vp_offset)
12696566cae7SDmytro Laktyushkin 			int_part = *vp_offset;
12706566cae7SDmytro Laktyushkin 		*vp_offset -= int_part;
12719b6067c0SDmytro Laktyushkin 		*init = dc_fixpt_add_int(*init, int_part);
12729b6067c0SDmytro Laktyushkin 	}
12739b6067c0SDmytro Laktyushkin 	/*
12746566cae7SDmytro Laktyushkin 	 * If taps are sampling outside of viewport at end of recout and there are more pixels
12756566cae7SDmytro Laktyushkin 	 * available in the surface we should increase the viewport size, regardless set vp to
12766566cae7SDmytro Laktyushkin 	 * only what is used.
12779b6067c0SDmytro Laktyushkin 	 */
12786566cae7SDmytro Laktyushkin 	temp = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_size - 1));
12796566cae7SDmytro Laktyushkin 	*vp_size = dc_fixpt_floor(temp);
12806566cae7SDmytro Laktyushkin 	if (*vp_size + *vp_offset > src_size)
12816566cae7SDmytro Laktyushkin 		*vp_size = src_size - *vp_offset;
12826566cae7SDmytro Laktyushkin 
12836566cae7SDmytro Laktyushkin 	/* We did all the math assuming we are scanning same direction as display does,
12846566cae7SDmytro Laktyushkin 	 * however mirror/rotation changes how vp scans vs how it is offset. If scan direction
12856566cae7SDmytro Laktyushkin 	 * is flipped we simply need to calculate offset from the other side of plane.
12866566cae7SDmytro Laktyushkin 	 * Note that outside of viewport all scaling hardware works in recout space.
12879b6067c0SDmytro Laktyushkin 	 */
12886566cae7SDmytro Laktyushkin 	if (flip_scan_dir)
12896566cae7SDmytro Laktyushkin 		*vp_offset = src_size - *vp_offset - *vp_size;
12909b6067c0SDmytro Laktyushkin }
12919b6067c0SDmytro Laktyushkin 
calculate_inits_and_viewports(struct pipe_ctx * pipe_ctx)12926566cae7SDmytro Laktyushkin static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx)
12939b6067c0SDmytro Laktyushkin {
12949b6067c0SDmytro Laktyushkin 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
12956702a9acSHarry Wentland 	struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
12966566cae7SDmytro Laktyushkin 	struct rect src = plane_state->src_rect;
12970f3b9542SWenjing Liu 	struct rect recout_dst_in_active_timing;
12980f3b9542SWenjing Liu 	struct rect recout_clip_in_active_timing;
12990f3b9542SWenjing Liu 	struct rect recout_clip_in_recout_dst;
1300e75b965eSWenjing Liu 	struct rect overlap_in_active_timing;
13010f3b9542SWenjing Liu 	struct rect odm_slice = calculate_odm_slice_in_timing_active(pipe_ctx);
130287449a90SAnthony Koo 	int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
130387449a90SAnthony Koo 				|| data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
13049b6067c0SDmytro Laktyushkin 	bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir;
13056566cae7SDmytro Laktyushkin 
13060f3b9542SWenjing Liu 	recout_clip_in_active_timing = shift_rec(
13070f3b9542SWenjing Liu 			&data->recout, odm_slice.x, odm_slice.y);
13080f3b9542SWenjing Liu 	recout_dst_in_active_timing = calculate_plane_rec_in_timing_active(
13090f3b9542SWenjing Liu 			pipe_ctx, &plane_state->dst_rect);
1310e75b965eSWenjing Liu 	overlap_in_active_timing = intersect_rec(&recout_clip_in_active_timing,
1311e75b965eSWenjing Liu 			&recout_dst_in_active_timing);
1312e75b965eSWenjing Liu 	if (overlap_in_active_timing.width > 0 &&
1313e75b965eSWenjing Liu 			overlap_in_active_timing.height > 0)
1314e75b965eSWenjing Liu 		recout_clip_in_recout_dst = shift_rec(&overlap_in_active_timing,
13150f3b9542SWenjing Liu 				-recout_dst_in_active_timing.x,
13160f3b9542SWenjing Liu 				-recout_dst_in_active_timing.y);
1317e75b965eSWenjing Liu 	else
1318e75b965eSWenjing Liu 		memset(&recout_clip_in_recout_dst, 0, sizeof(struct rect));
1319e75b965eSWenjing Liu 
1320b0131391SDmytro Laktyushkin 	/*
13216566cae7SDmytro Laktyushkin 	 * Work in recout rotation since that requires less transformations
1322b0131391SDmytro Laktyushkin 	 */
13239b6067c0SDmytro Laktyushkin 	get_vp_scan_direction(
13249b6067c0SDmytro Laktyushkin 			plane_state->rotation,
13259b6067c0SDmytro Laktyushkin 			plane_state->horizontal_mirror,
13269b6067c0SDmytro Laktyushkin 			&orthogonal_rotation,
13279b6067c0SDmytro Laktyushkin 			&flip_vert_scan_dir,
13289b6067c0SDmytro Laktyushkin 			&flip_horz_scan_dir);
1329b0131391SDmytro Laktyushkin 
13309b6067c0SDmytro Laktyushkin 	if (orthogonal_rotation) {
13319b6067c0SDmytro Laktyushkin 		swap(src.width, src.height);
13326566cae7SDmytro Laktyushkin 		swap(flip_vert_scan_dir, flip_horz_scan_dir);
13339b5349f7SMartin Tsai 	}
13341fbd2cfcSDmytro Laktyushkin 
13356566cae7SDmytro Laktyushkin 	calculate_init_and_vp(
13369b6067c0SDmytro Laktyushkin 			flip_horz_scan_dir,
13370f3b9542SWenjing Liu 			recout_clip_in_recout_dst.x,
13386566cae7SDmytro Laktyushkin 			data->recout.width,
13396566cae7SDmytro Laktyushkin 			src.width,
13406566cae7SDmytro Laktyushkin 			data->taps.h_taps,
13416566cae7SDmytro Laktyushkin 			data->ratios.horz,
13426566cae7SDmytro Laktyushkin 			&data->inits.h,
13439b6067c0SDmytro Laktyushkin 			&data->viewport.x,
13449b6067c0SDmytro Laktyushkin 			&data->viewport.width);
13456566cae7SDmytro Laktyushkin 	calculate_init_and_vp(
13469b6067c0SDmytro Laktyushkin 			flip_horz_scan_dir,
13470f3b9542SWenjing Liu 			recout_clip_in_recout_dst.x,
13486566cae7SDmytro Laktyushkin 			data->recout.width,
13496566cae7SDmytro Laktyushkin 			src.width / vpc_div,
13506566cae7SDmytro Laktyushkin 			data->taps.h_taps_c,
13516566cae7SDmytro Laktyushkin 			data->ratios.horz_c,
13526566cae7SDmytro Laktyushkin 			&data->inits.h_c,
13539b6067c0SDmytro Laktyushkin 			&data->viewport_c.x,
13549b6067c0SDmytro Laktyushkin 			&data->viewport_c.width);
13556566cae7SDmytro Laktyushkin 	calculate_init_and_vp(
13569b6067c0SDmytro Laktyushkin 			flip_vert_scan_dir,
13570f3b9542SWenjing Liu 			recout_clip_in_recout_dst.y,
13586566cae7SDmytro Laktyushkin 			data->recout.height,
13596566cae7SDmytro Laktyushkin 			src.height,
13606566cae7SDmytro Laktyushkin 			data->taps.v_taps,
13616566cae7SDmytro Laktyushkin 			data->ratios.vert,
13626566cae7SDmytro Laktyushkin 			&data->inits.v,
13639b6067c0SDmytro Laktyushkin 			&data->viewport.y,
13649b6067c0SDmytro Laktyushkin 			&data->viewport.height);
13656566cae7SDmytro Laktyushkin 	calculate_init_and_vp(
13669b6067c0SDmytro Laktyushkin 			flip_vert_scan_dir,
13670f3b9542SWenjing Liu 			recout_clip_in_recout_dst.y,
13686566cae7SDmytro Laktyushkin 			data->recout.height,
13696566cae7SDmytro Laktyushkin 			src.height / vpc_div,
13706566cae7SDmytro Laktyushkin 			data->taps.v_taps_c,
13716566cae7SDmytro Laktyushkin 			data->ratios.vert_c,
13726566cae7SDmytro Laktyushkin 			&data->inits.v_c,
13739b6067c0SDmytro Laktyushkin 			&data->viewport_c.y,
13749b6067c0SDmytro Laktyushkin 			&data->viewport_c.height);
13756566cae7SDmytro Laktyushkin 	if (orthogonal_rotation) {
13766566cae7SDmytro Laktyushkin 		swap(data->viewport.x, data->viewport.y);
13776566cae7SDmytro Laktyushkin 		swap(data->viewport.width, data->viewport.height);
13786566cae7SDmytro Laktyushkin 		swap(data->viewport_c.x, data->viewport_c.y);
13796566cae7SDmytro Laktyushkin 		swap(data->viewport_c.width, data->viewport_c.height);
1380b2d0a103SDmytro Laktyushkin 	}
13816566cae7SDmytro Laktyushkin 	data->viewport.x += src.x;
13826566cae7SDmytro Laktyushkin 	data->viewport.y += src.y;
13836566cae7SDmytro Laktyushkin 	ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0);
13846566cae7SDmytro Laktyushkin 	data->viewport_c.x += src.x / vpc_div;
13856566cae7SDmytro Laktyushkin 	data->viewport_c.y += src.y / vpc_div;
138689d07b66SSamson Tam }
138789d07b66SSamson Tam 
resource_build_scaling_params(struct pipe_ctx * pipe_ctx)1388b2d0a103SDmytro Laktyushkin bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
1389b2d0a103SDmytro Laktyushkin {
13903be5262eSHarry Wentland 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
13914fa086b9SLeo (Sunpeng) Li 	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
13920f3b9542SWenjing Liu 	const struct rect odm_slice_rec = calculate_odm_slice_in_timing_active(pipe_ctx);
1393b2d0a103SDmytro Laktyushkin 	bool res = false;
13945d4b05ddSBhawanpreet Lakha 	DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
13956566cae7SDmytro Laktyushkin 
139673b1da69SMichael Strauss 	/* Invalid input */
139773b1da69SMichael Strauss 	if (!plane_state->dst_rect.width ||
139873b1da69SMichael Strauss 			!plane_state->dst_rect.height ||
139973b1da69SMichael Strauss 			!plane_state->src_rect.width ||
140073b1da69SMichael Strauss 			!plane_state->src_rect.height) {
140173b1da69SMichael Strauss 		ASSERT(0);
140273b1da69SMichael Strauss 		return false;
140373b1da69SMichael Strauss 	}
140473b1da69SMichael Strauss 
14056702a9acSHarry Wentland 	pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
14063be5262eSHarry Wentland 			pipe_ctx->plane_state->format);
14074562236bSHarry Wentland 
14086566cae7SDmytro Laktyushkin 	/* Timing borders are part of vactive that we are also supposed to skip in addition
14096566cae7SDmytro Laktyushkin 	 * to any stream dst offset. Since dm logic assumes dst is in addressable
14104dc8e494SCai Huoqing 	 * space we need to add the left and top borders to dst offsets temporarily.
14116566cae7SDmytro Laktyushkin 	 * TODO: fix in DM, stream dst is supposed to be in vactive
14126566cae7SDmytro Laktyushkin 	 */
14136566cae7SDmytro Laktyushkin 	pipe_ctx->stream->dst.x += timing->h_border_left;
14146566cae7SDmytro Laktyushkin 	pipe_ctx->stream->dst.y += timing->v_border_top;
1415b2d0a103SDmytro Laktyushkin 
14166566cae7SDmytro Laktyushkin 	/* Calculate H and V active size */
14170f3b9542SWenjing Liu 	pipe_ctx->plane_res.scl_data.h_active = odm_slice_rec.width;
14180f3b9542SWenjing Liu 	pipe_ctx->plane_res.scl_data.v_active = odm_slice_rec.height;
14194562236bSHarry Wentland 
14206566cae7SDmytro Laktyushkin 	/* depends on h_active */
14219b6067c0SDmytro Laktyushkin 	calculate_recout(pipe_ctx);
14226566cae7SDmytro Laktyushkin 	/* depends on pixel format */
14236566cae7SDmytro Laktyushkin 	calculate_scaling_ratios(pipe_ctx);
14246566cae7SDmytro Laktyushkin 	/* depends on scaling ratios and recout, does not calculate offset yet */
14256566cae7SDmytro Laktyushkin 	calculate_viewport_size(pipe_ctx);
14264562236bSHarry Wentland 
14279dfc3ee1SSamson Tam 	if (!pipe_ctx->stream->ctx->dc->config.enable_windowed_mpo_odm) {
142847547c56SMartin Leung 		/* Stopgap for validation of ODM + MPO on one side of screen case */
142947547c56SMartin Leung 		if (pipe_ctx->plane_res.scl_data.viewport.height < 1 ||
143047547c56SMartin Leung 				pipe_ctx->plane_res.scl_data.viewport.width < 1)
143147547c56SMartin Leung 			return false;
14329dfc3ee1SSamson Tam 	}
143347547c56SMartin Leung 
14346566cae7SDmytro Laktyushkin 	/*
14356566cae7SDmytro Laktyushkin 	 * LB calculations depend on vp size, h/v_active and scaling ratios
14364562236bSHarry Wentland 	 * Setting line buffer pixel depth to 24bpp yields banding
1437a316db72SMario Kleiner 	 * on certain displays, such as the Sharp 4k. 36bpp is needed
1438a316db72SMario Kleiner 	 * to support SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 and
1439a316db72SMario Kleiner 	 * SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 with actual > 10 bpc
1440cb508139SMario Kleiner 	 * precision on DCN display engines, but apparently not for DCE, as
1441cb508139SMario Kleiner 	 * far as testing on DCE-11.2 and DCE-8 showed. Various DCE parts have
1442cb508139SMario Kleiner 	 * problems: Carrizo with DCE_VERSION_11_0 does not like 36 bpp lb depth,
1443cb508139SMario Kleiner 	 * neither do DCE-8 at 4k resolution, or DCE-11.2 (broken identify pixel
1444cb508139SMario Kleiner 	 * passthrough). Therefore only use 36 bpp on DCN where it is actually needed.
14454562236bSHarry Wentland 	 */
1446cb508139SMario Kleiner 	if (plane_state->ctx->dce_version > DCE_VERSION_MAX)
1447a316db72SMario Kleiner 		pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_36BPP;
144872a7cf0aSMario Kleiner 	else
144972a7cf0aSMario Kleiner 		pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
145072a7cf0aSMario Kleiner 
145133eef72fSEric Bernstein 	pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
14524562236bSHarry Wentland 
1453d94585a0SYue Hin Lau 	if (pipe_ctx->plane_res.xfm != NULL)
145486a66c4eSHarry Wentland 		res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
145586a66c4eSHarry Wentland 				pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
14564562236bSHarry Wentland 
1457d94585a0SYue Hin Lau 	if (pipe_ctx->plane_res.dpp != NULL)
1458d94585a0SYue Hin Lau 		res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
1459d94585a0SYue Hin Lau 				pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
1460f7938bc0SReza Amini 
1461f7938bc0SReza Amini 
14624562236bSHarry Wentland 	if (!res) {
14634562236bSHarry Wentland 		/* Try 24 bpp linebuffer */
14646702a9acSHarry Wentland 		pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
14654562236bSHarry Wentland 
14661b6c8067SBhawanpreet Lakha 		if (pipe_ctx->plane_res.xfm != NULL)
146786a66c4eSHarry Wentland 			res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
14681b6c8067SBhawanpreet Lakha 					pipe_ctx->plane_res.xfm,
14691b6c8067SBhawanpreet Lakha 					&pipe_ctx->plane_res.scl_data,
14701b6c8067SBhawanpreet Lakha 					&plane_state->scaling_quality);
1471d94585a0SYue Hin Lau 
14721b6c8067SBhawanpreet Lakha 		if (pipe_ctx->plane_res.dpp != NULL)
1473d94585a0SYue Hin Lau 			res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
14741b6c8067SBhawanpreet Lakha 					pipe_ctx->plane_res.dpp,
14751b6c8067SBhawanpreet Lakha 					&pipe_ctx->plane_res.scl_data,
14761b6c8067SBhawanpreet Lakha 					&plane_state->scaling_quality);
14774562236bSHarry Wentland 	}
14784562236bSHarry Wentland 
14796566cae7SDmytro Laktyushkin 	/*
14806566cae7SDmytro Laktyushkin 	 * Depends on recout, scaling ratios, h_active and taps
14816566cae7SDmytro Laktyushkin 	 * May need to re-check lb size after this in some obscure scenario
14826566cae7SDmytro Laktyushkin 	 */
1483b2d0a103SDmytro Laktyushkin 	if (res)
14846566cae7SDmytro Laktyushkin 		calculate_inits_and_viewports(pipe_ctx);
14856566cae7SDmytro Laktyushkin 
14866566cae7SDmytro Laktyushkin 	/*
14876566cae7SDmytro Laktyushkin 	 * Handle side by side and top bottom 3d recout offsets after vp calculation
14886566cae7SDmytro Laktyushkin 	 * since 3d is special and needs to calculate vp as if there is no recout offset
14896566cae7SDmytro Laktyushkin 	 * This may break with rotation, good thing we aren't mixing hw rotation and 3d
14906566cae7SDmytro Laktyushkin 	 */
14916566cae7SDmytro Laktyushkin 	if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == plane_state) {
14926566cae7SDmytro Laktyushkin 		ASSERT(plane_state->rotation == ROTATION_ANGLE_0 ||
14936566cae7SDmytro Laktyushkin 			(pipe_ctx->stream->view_format != VIEW_3D_FORMAT_TOP_AND_BOTTOM &&
14946566cae7SDmytro Laktyushkin 				pipe_ctx->stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE));
14956566cae7SDmytro Laktyushkin 		if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
14966566cae7SDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height;
14976566cae7SDmytro Laktyushkin 		else if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
14986566cae7SDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width;
14996566cae7SDmytro Laktyushkin 	}
15006566cae7SDmytro Laktyushkin 
15017db581d6SDmytro Laktyushkin 	/* Clamp minimum viewport size */
15027db581d6SDmytro Laktyushkin 	if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE)
15037db581d6SDmytro Laktyushkin 		pipe_ctx->plane_res.scl_data.viewport.height = MIN_VIEWPORT_SIZE;
15047db581d6SDmytro Laktyushkin 	if (pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
15057db581d6SDmytro Laktyushkin 		pipe_ctx->plane_res.scl_data.viewport.width = MIN_VIEWPORT_SIZE;
1506e75b965eSWenjing Liu 
1507b2d0a103SDmytro Laktyushkin 
15083c0dcf9fSDmytro Laktyushkin 	DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d  Recout: height:%d width:%d x:%d y:%d  HACTIVE:%d VACTIVE:%d\n"
15093c0dcf9fSDmytro Laktyushkin 			"src_rect: height:%d width:%d x:%d y:%d  dst_rect: height:%d width:%d x:%d y:%d  clip_rect: height:%d width:%d x:%d y:%d\n",
15104562236bSHarry Wentland 			__func__,
15113c0dcf9fSDmytro Laktyushkin 			pipe_ctx->pipe_idx,
15126702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.viewport.height,
15136702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.viewport.width,
15146702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.viewport.x,
15156702a9acSHarry Wentland 			pipe_ctx->plane_res.scl_data.viewport.y,
15163c0dcf9fSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.recout.height,
15173c0dcf9fSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.recout.width,
15183c0dcf9fSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.recout.x,
15193c0dcf9fSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.recout.y,
15203c0dcf9fSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.h_active,
15213c0dcf9fSDmytro Laktyushkin 			pipe_ctx->plane_res.scl_data.v_active,
15223c0dcf9fSDmytro Laktyushkin 			plane_state->src_rect.height,
15233c0dcf9fSDmytro Laktyushkin 			plane_state->src_rect.width,
15243c0dcf9fSDmytro Laktyushkin 			plane_state->src_rect.x,
15253c0dcf9fSDmytro Laktyushkin 			plane_state->src_rect.y,
15263be5262eSHarry Wentland 			plane_state->dst_rect.height,
15273be5262eSHarry Wentland 			plane_state->dst_rect.width,
15283be5262eSHarry Wentland 			plane_state->dst_rect.x,
15293c0dcf9fSDmytro Laktyushkin 			plane_state->dst_rect.y,
15303c0dcf9fSDmytro Laktyushkin 			plane_state->clip_rect.height,
15313c0dcf9fSDmytro Laktyushkin 			plane_state->clip_rect.width,
15323c0dcf9fSDmytro Laktyushkin 			plane_state->clip_rect.x,
15333c0dcf9fSDmytro Laktyushkin 			plane_state->clip_rect.y);
15344562236bSHarry Wentland 
15356566cae7SDmytro Laktyushkin 	pipe_ctx->stream->dst.x -= timing->h_border_left;
15366566cae7SDmytro Laktyushkin 	pipe_ctx->stream->dst.y -= timing->v_border_top;
153789d07b66SSamson Tam 
15384562236bSHarry Wentland 	return res;
15394562236bSHarry Wentland }
15404562236bSHarry Wentland 
15414562236bSHarry Wentland 
resource_build_scaling_params_for_context(const struct dc * dc,struct dc_state * context)15424562236bSHarry Wentland enum dc_status resource_build_scaling_params_for_context(
1543fb3466a4SBhawanpreet Lakha 	const struct dc  *dc,
1544608ac7bbSJerry Zuo 	struct dc_state *context)
15454562236bSHarry Wentland {
15464562236bSHarry Wentland 	int i;
15474562236bSHarry Wentland 
15484562236bSHarry Wentland 	for (i = 0; i < MAX_PIPES; i++) {
15493be5262eSHarry Wentland 		if (context->res_ctx.pipe_ctx[i].plane_state != NULL &&
15504562236bSHarry Wentland 				context->res_ctx.pipe_ctx[i].stream != NULL)
1551b2d0a103SDmytro Laktyushkin 			if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i]))
1552f84a8161STony Cheng 				return DC_FAIL_SCALING;
15534562236bSHarry Wentland 	}
15544562236bSHarry Wentland 
15554562236bSHarry Wentland 	return DC_OK;
15564562236bSHarry Wentland }
15574562236bSHarry Wentland 
resource_find_free_secondary_pipe_legacy(struct resource_context * res_ctx,const struct resource_pool * pool,const struct pipe_ctx * primary_pipe)155853f32880SWenjing Liu struct pipe_ctx *resource_find_free_secondary_pipe_legacy(
1559a2b8659dSTony Cheng 		struct resource_context *res_ctx,
15605581192dSJun Lei 		const struct resource_pool *pool,
15615581192dSJun Lei 		const struct pipe_ctx *primary_pipe)
15624562236bSHarry Wentland {
15634562236bSHarry Wentland 	int i;
15644562236bSHarry Wentland 	struct pipe_ctx *secondary_pipe = NULL;
15654562236bSHarry Wentland 
15664562236bSHarry Wentland 	/*
15675581192dSJun Lei 	 * We add a preferred pipe mapping to avoid the chance that
15685581192dSJun Lei 	 * MPCCs already in use will need to be reassigned to other trees.
15695581192dSJun Lei 	 * For example, if we went with the strict, assign backwards logic:
15705581192dSJun Lei 	 *
15715581192dSJun Lei 	 * (State 1)
15725581192dSJun Lei 	 * Display A on, no surface, top pipe = 0
15735581192dSJun Lei 	 * Display B on, no surface, top pipe = 1
15745581192dSJun Lei 	 *
15755581192dSJun Lei 	 * (State 2)
15765581192dSJun Lei 	 * Display A on, no surface, top pipe = 0
15775581192dSJun Lei 	 * Display B on, surface enable, top pipe = 1, bottom pipe = 5
15785581192dSJun Lei 	 *
15795581192dSJun Lei 	 * (State 3)
15805581192dSJun Lei 	 * Display A on, surface enable, top pipe = 0, bottom pipe = 5
15815581192dSJun Lei 	 * Display B on, surface enable, top pipe = 1, bottom pipe = 4
15825581192dSJun Lei 	 *
15835581192dSJun Lei 	 * The state 2->3 transition requires remapping MPCC 5 from display B
15845581192dSJun Lei 	 * to display A.
15855581192dSJun Lei 	 *
15865581192dSJun Lei 	 * However, with the preferred pipe logic, state 2 would look like:
15875581192dSJun Lei 	 *
15885581192dSJun Lei 	 * (State 2)
15895581192dSJun Lei 	 * Display A on, no surface, top pipe = 0
15905581192dSJun Lei 	 * Display B on, surface enable, top pipe = 1, bottom pipe = 4
15915581192dSJun Lei 	 *
15925581192dSJun Lei 	 * This would then cause 2->3 to not require remapping any MPCCs.
15935581192dSJun Lei 	 */
15945581192dSJun Lei 	if (primary_pipe) {
15955581192dSJun Lei 		int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
15965581192dSJun Lei 		if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
15975581192dSJun Lei 			secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
15985581192dSJun Lei 			secondary_pipe->pipe_idx = preferred_pipe_idx;
15995581192dSJun Lei 		}
16005581192dSJun Lei 	}
16015581192dSJun Lei 
16025581192dSJun Lei 	/*
16034562236bSHarry Wentland 	 * search backwards for the second pipe to keep pipe
16044562236bSHarry Wentland 	 * assignment more consistent
16054562236bSHarry Wentland 	 */
16065581192dSJun Lei 	if (!secondary_pipe)
1607a2b8659dSTony Cheng 		for (i = pool->pipe_count - 1; i >= 0; i--) {
16084562236bSHarry Wentland 			if (res_ctx->pipe_ctx[i].stream == NULL) {
16094562236bSHarry Wentland 				secondary_pipe = &res_ctx->pipe_ctx[i];
16104562236bSHarry Wentland 				secondary_pipe->pipe_idx = i;
16114562236bSHarry Wentland 				break;
16124562236bSHarry Wentland 			}
16134562236bSHarry Wentland 		}
16144562236bSHarry Wentland 
16154562236bSHarry Wentland 	return secondary_pipe;
16164562236bSHarry Wentland }
16174562236bSHarry Wentland 
resource_find_free_pipe_used_in_cur_mpc_blending_tree(const struct resource_context * cur_res_ctx,struct resource_context * new_res_ctx,const struct pipe_ctx * cur_opp_head)1618198f0e89SWenjing Liu int resource_find_free_pipe_used_in_cur_mpc_blending_tree(
1619460ea898SWenjing Liu 		const struct resource_context *cur_res_ctx,
1620460ea898SWenjing Liu 		struct resource_context *new_res_ctx,
1621d8e3fcd3SWenjing Liu 		const struct pipe_ctx *cur_opp_head)
1622460ea898SWenjing Liu {
1623d8e3fcd3SWenjing Liu 	const struct pipe_ctx *cur_sec_dpp = cur_opp_head->bottom_pipe;
162453f32880SWenjing Liu 	struct pipe_ctx *new_pipe;
1625198f0e89SWenjing Liu 	int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
1626460ea898SWenjing Liu 
1627d8e3fcd3SWenjing Liu 	while (cur_sec_dpp) {
1628198f0e89SWenjing Liu 		/* find a free pipe used in current opp blend tree,
1629460ea898SWenjing Liu 		 * this is to avoid MPO pipe switching to different opp blending
1630460ea898SWenjing Liu 		 * tree
1631460ea898SWenjing Liu 		 */
163253f32880SWenjing Liu 		new_pipe = &new_res_ctx->pipe_ctx[cur_sec_dpp->pipe_idx];
163353f32880SWenjing Liu 		if (resource_is_pipe_type(new_pipe, FREE_PIPE)) {
1634198f0e89SWenjing Liu 			free_pipe_idx = cur_sec_dpp->pipe_idx;
1635460ea898SWenjing Liu 			break;
1636460ea898SWenjing Liu 		}
1637d8e3fcd3SWenjing Liu 		cur_sec_dpp = cur_sec_dpp->bottom_pipe;
1638460ea898SWenjing Liu 	}
1639460ea898SWenjing Liu 
1640198f0e89SWenjing Liu 	return free_pipe_idx;
1641d8e3fcd3SWenjing Liu }
1642d8e3fcd3SWenjing Liu 
recource_find_free_pipe_not_used_in_cur_res_ctx(const struct resource_context * cur_res_ctx,struct resource_context * new_res_ctx,const struct resource_pool * pool)1643198f0e89SWenjing Liu int recource_find_free_pipe_not_used_in_cur_res_ctx(
1644d8e3fcd3SWenjing Liu 		const struct resource_context *cur_res_ctx,
1645d8e3fcd3SWenjing Liu 		struct resource_context *new_res_ctx,
1646d8e3fcd3SWenjing Liu 		const struct resource_pool *pool)
1647d8e3fcd3SWenjing Liu {
1648198f0e89SWenjing Liu 	int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
164953f32880SWenjing Liu 	const struct pipe_ctx *new_pipe, *cur_pipe;
1650d8e3fcd3SWenjing Liu 	int i;
1651d8e3fcd3SWenjing Liu 
1652460ea898SWenjing Liu 	for (i = 0; i < pool->pipe_count; i++) {
165353f32880SWenjing Liu 		cur_pipe = &cur_res_ctx->pipe_ctx[i];
165453f32880SWenjing Liu 		new_pipe = &new_res_ctx->pipe_ctx[i];
1655460ea898SWenjing Liu 
165653f32880SWenjing Liu 		if (resource_is_pipe_type(cur_pipe, FREE_PIPE) &&
165753f32880SWenjing Liu 				resource_is_pipe_type(new_pipe, FREE_PIPE)) {
1658198f0e89SWenjing Liu 			free_pipe_idx = i;
1659460ea898SWenjing Liu 			break;
1660460ea898SWenjing Liu 		}
1661460ea898SWenjing Liu 	}
1662d8e3fcd3SWenjing Liu 
1663198f0e89SWenjing Liu 	return free_pipe_idx;
1664460ea898SWenjing Liu }
1665460ea898SWenjing Liu 
resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine(const struct resource_context * cur_res_ctx,struct resource_context * new_res_ctx,const struct resource_pool * pool)1666198f0e89SWenjing Liu int resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine(
1667d8e3fcd3SWenjing Liu 		const struct resource_context *cur_res_ctx,
1668d8e3fcd3SWenjing Liu 		struct resource_context *new_res_ctx,
1669d8e3fcd3SWenjing Liu 		const struct resource_pool *pool)
1670d8e3fcd3SWenjing Liu {
1671198f0e89SWenjing Liu 	int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
167253f32880SWenjing Liu 	const struct pipe_ctx *new_pipe, *cur_pipe;
1673d8e3fcd3SWenjing Liu 	int i;
1674d8e3fcd3SWenjing Liu 
1675460ea898SWenjing Liu 	for (i = 0; i < pool->pipe_count; i++) {
167653f32880SWenjing Liu 		cur_pipe = &cur_res_ctx->pipe_ctx[i];
167753f32880SWenjing Liu 		new_pipe = &new_res_ctx->pipe_ctx[i];
1678460ea898SWenjing Liu 
167953f32880SWenjing Liu 		if (resource_is_pipe_type(cur_pipe, DPP_PIPE) &&
168053f32880SWenjing Liu 				!resource_is_pipe_type(cur_pipe, OPP_HEAD) &&
168153f32880SWenjing Liu 				resource_is_for_mpcc_combine(cur_pipe) &&
168253f32880SWenjing Liu 				resource_is_pipe_type(new_pipe, FREE_PIPE)) {
1683198f0e89SWenjing Liu 			free_pipe_idx = i;
1684460ea898SWenjing Liu 			break;
1685460ea898SWenjing Liu 		}
1686460ea898SWenjing Liu 	}
1687d8e3fcd3SWenjing Liu 
1688198f0e89SWenjing Liu 	return free_pipe_idx;
1689460ea898SWenjing Liu }
1690460ea898SWenjing Liu 
resource_find_any_free_pipe(struct resource_context * new_res_ctx,const struct resource_pool * pool)1691198f0e89SWenjing Liu int resource_find_any_free_pipe(struct resource_context *new_res_ctx,
1692d8e3fcd3SWenjing Liu 		const struct resource_pool *pool)
1693d8e3fcd3SWenjing Liu {
1694198f0e89SWenjing Liu 	int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
169553f32880SWenjing Liu 	const struct pipe_ctx *new_pipe;
1696d8e3fcd3SWenjing Liu 	int i;
1697d8e3fcd3SWenjing Liu 
1698460ea898SWenjing Liu 	for (i = 0; i < pool->pipe_count; i++) {
169953f32880SWenjing Liu 		new_pipe = &new_res_ctx->pipe_ctx[i];
1700460ea898SWenjing Liu 
170153f32880SWenjing Liu 		if (resource_is_pipe_type(new_pipe, FREE_PIPE)) {
1702198f0e89SWenjing Liu 			free_pipe_idx = i;
1703460ea898SWenjing Liu 			break;
1704460ea898SWenjing Liu 		}
1705460ea898SWenjing Liu 	}
1706460ea898SWenjing Liu 
1707198f0e89SWenjing Liu 	return free_pipe_idx;
1708460ea898SWenjing Liu }
1709460ea898SWenjing Liu 
resource_is_pipe_type(const struct pipe_ctx * pipe_ctx,enum pipe_type type)171053f32880SWenjing Liu bool resource_is_pipe_type(const struct pipe_ctx *pipe_ctx, enum pipe_type type)
171153f32880SWenjing Liu {
171253f32880SWenjing Liu #ifdef DBG
171353f32880SWenjing Liu 	if (pipe_ctx->stream == NULL) {
171453f32880SWenjing Liu 		/* a free pipe with dangling states */
171553f32880SWenjing Liu 		ASSERT(!pipe_ctx->plane_state);
171653f32880SWenjing Liu 		ASSERT(!pipe_ctx->prev_odm_pipe);
171753f32880SWenjing Liu 		ASSERT(!pipe_ctx->next_odm_pipe);
171853f32880SWenjing Liu 		ASSERT(!pipe_ctx->top_pipe);
171953f32880SWenjing Liu 		ASSERT(!pipe_ctx->bottom_pipe);
172053f32880SWenjing Liu 	} else if (pipe_ctx->top_pipe) {
172153f32880SWenjing Liu 		/* a secondary DPP pipe must be signed to a plane */
172253f32880SWenjing Liu 		ASSERT(pipe_ctx->plane_state)
172353f32880SWenjing Liu 	}
172453f32880SWenjing Liu 	/* Add more checks here to prevent corrupted pipe ctx. It is very hard
172553f32880SWenjing Liu 	 * to debug this issue afterwards because we can't pinpoint the code
172653f32880SWenjing Liu 	 * location causing inconsistent pipe context states.
1727460ea898SWenjing Liu 	 */
172853f32880SWenjing Liu #endif
172953f32880SWenjing Liu 	switch (type) {
173053f32880SWenjing Liu 	case OTG_MASTER:
173153f32880SWenjing Liu 		return !pipe_ctx->prev_odm_pipe &&
173253f32880SWenjing Liu 				!pipe_ctx->top_pipe &&
173353f32880SWenjing Liu 				pipe_ctx->stream;
173453f32880SWenjing Liu 	case OPP_HEAD:
173553f32880SWenjing Liu 		return !pipe_ctx->top_pipe && pipe_ctx->stream;
173653f32880SWenjing Liu 	case DPP_PIPE:
173753f32880SWenjing Liu 		return pipe_ctx->plane_state && pipe_ctx->stream;
173853f32880SWenjing Liu 	case FREE_PIPE:
173953f32880SWenjing Liu 		return !pipe_ctx->plane_state && !pipe_ctx->stream;
174053f32880SWenjing Liu 	default:
174153f32880SWenjing Liu 		return false;
174253f32880SWenjing Liu 	}
174353f32880SWenjing Liu }
174453f32880SWenjing Liu 
resource_is_for_mpcc_combine(const struct pipe_ctx * pipe_ctx)174553f32880SWenjing Liu bool resource_is_for_mpcc_combine(const struct pipe_ctx *pipe_ctx)
174653f32880SWenjing Liu {
174753f32880SWenjing Liu 	return resource_get_num_mpc_splits(pipe_ctx) > 0;
174853f32880SWenjing Liu }
174953f32880SWenjing Liu 
resource_get_otg_master_for_stream(struct resource_context * res_ctx,struct dc_stream_state * stream)175053f32880SWenjing Liu struct pipe_ctx *resource_get_otg_master_for_stream(
17514562236bSHarry Wentland 		struct resource_context *res_ctx,
17520971c40eSHarry Wentland 		struct dc_stream_state *stream)
17534562236bSHarry Wentland {
17544562236bSHarry Wentland 	int i;
175522498036SDmytro Laktyushkin 
1756a2b8659dSTony Cheng 	for (i = 0; i < MAX_PIPES; i++) {
175753f32880SWenjing Liu 		if (res_ctx->pipe_ctx[i].stream == stream &&
175853f32880SWenjing Liu 				resource_is_pipe_type(&res_ctx->pipe_ctx[i], OTG_MASTER))
17594562236bSHarry Wentland 			return &res_ctx->pipe_ctx[i];
17604562236bSHarry Wentland 	}
17614562236bSHarry Wentland 	return NULL;
17624562236bSHarry Wentland }
17634562236bSHarry Wentland 
resource_get_otg_master(const struct pipe_ctx * pipe_ctx)176453f32880SWenjing Liu struct pipe_ctx *resource_get_otg_master(const struct pipe_ctx *pipe_ctx)
176553f32880SWenjing Liu {
176653f32880SWenjing Liu 	struct pipe_ctx *otg_master = resource_get_opp_head(pipe_ctx);
176753f32880SWenjing Liu 
176853f32880SWenjing Liu 	while (otg_master->prev_odm_pipe)
176953f32880SWenjing Liu 		otg_master = otg_master->prev_odm_pipe;
177053f32880SWenjing Liu 	return otg_master;
177153f32880SWenjing Liu }
177253f32880SWenjing Liu 
resource_get_opp_head(const struct pipe_ctx * pipe_ctx)177353f32880SWenjing Liu struct pipe_ctx *resource_get_opp_head(const struct pipe_ctx *pipe_ctx)
177453f32880SWenjing Liu {
177553f32880SWenjing Liu 	struct pipe_ctx *opp_head = (struct pipe_ctx *) pipe_ctx;
177653f32880SWenjing Liu 
177753f32880SWenjing Liu 	ASSERT(!resource_is_pipe_type(opp_head, FREE_PIPE));
177853f32880SWenjing Liu 	while (opp_head->top_pipe)
177953f32880SWenjing Liu 		opp_head = opp_head->top_pipe;
178053f32880SWenjing Liu 	return opp_head;
178153f32880SWenjing Liu }
178253f32880SWenjing Liu 
get_tail_pipe(struct pipe_ctx * head_pipe)1783460ea898SWenjing Liu static struct pipe_ctx *get_tail_pipe(
1784b1f6d01cSDmytro Laktyushkin 		struct pipe_ctx *head_pipe)
178519f89e23SAndrey Grodzovsky {
178653f32880SWenjing Liu 	struct pipe_ctx *tail_pipe = head_pipe->bottom_pipe;
178719f89e23SAndrey Grodzovsky 
178819f89e23SAndrey Grodzovsky 	while (tail_pipe) {
178919f89e23SAndrey Grodzovsky 		head_pipe = tail_pipe;
179019f89e23SAndrey Grodzovsky 		tail_pipe = tail_pipe->bottom_pipe;
179119f89e23SAndrey Grodzovsky 	}
179219f89e23SAndrey Grodzovsky 
179319f89e23SAndrey Grodzovsky 	return head_pipe;
179419f89e23SAndrey Grodzovsky }
179519f89e23SAndrey Grodzovsky 
acquire_first_split_pipe(struct resource_context * res_ctx,const struct resource_pool * pool,struct dc_stream_state * stream)17960f9a536fSDmytro Laktyushkin static int acquire_first_split_pipe(
17970f9a536fSDmytro Laktyushkin 		struct resource_context *res_ctx,
17980f9a536fSDmytro Laktyushkin 		const struct resource_pool *pool,
17990971c40eSHarry Wentland 		struct dc_stream_state *stream)
18000f9a536fSDmytro Laktyushkin {
18010f9a536fSDmytro Laktyushkin 	int i;
18020f9a536fSDmytro Laktyushkin 
18030f9a536fSDmytro Laktyushkin 	for (i = 0; i < pool->pipe_count; i++) {
180479592db3SDmytro Laktyushkin 		struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i];
18050f9a536fSDmytro Laktyushkin 
1806b1f6d01cSDmytro Laktyushkin 		if (split_pipe->top_pipe &&
180779592db3SDmytro Laktyushkin 				split_pipe->top_pipe->plane_state == split_pipe->plane_state) {
180879592db3SDmytro Laktyushkin 			split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe;
180979592db3SDmytro Laktyushkin 			if (split_pipe->bottom_pipe)
181079592db3SDmytro Laktyushkin 				split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe;
18110f9a536fSDmytro Laktyushkin 
181279592db3SDmytro Laktyushkin 			if (split_pipe->top_pipe->plane_state)
181379592db3SDmytro Laktyushkin 				resource_build_scaling_params(split_pipe->top_pipe);
18140f9a536fSDmytro Laktyushkin 
181579592db3SDmytro Laktyushkin 			memset(split_pipe, 0, sizeof(*split_pipe));
181679592db3SDmytro Laktyushkin 			split_pipe->stream_res.tg = pool->timing_generators[i];
181779592db3SDmytro Laktyushkin 			split_pipe->plane_res.hubp = pool->hubps[i];
181879592db3SDmytro Laktyushkin 			split_pipe->plane_res.ipp = pool->ipps[i];
181979592db3SDmytro Laktyushkin 			split_pipe->plane_res.dpp = pool->dpps[i];
182079592db3SDmytro Laktyushkin 			split_pipe->stream_res.opp = pool->opps[i];
182179592db3SDmytro Laktyushkin 			split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst;
182279592db3SDmytro Laktyushkin 			split_pipe->pipe_idx = i;
182379592db3SDmytro Laktyushkin 
182479592db3SDmytro Laktyushkin 			split_pipe->stream = stream;
18250f9a536fSDmytro Laktyushkin 			return i;
18260f9a536fSDmytro Laktyushkin 		}
18270f9a536fSDmytro Laktyushkin 	}
182875bd42fdSEthan Bitnun 	return UNABLE_TO_SPLIT;
18290f9a536fSDmytro Laktyushkin }
18300f9a536fSDmytro Laktyushkin 
add_plane_to_opp_head_pipes(struct pipe_ctx * otg_master_pipe,struct dc_plane_state * plane_state,struct dc_state * context)1831460ea898SWenjing Liu static bool add_plane_to_opp_head_pipes(struct pipe_ctx *otg_master_pipe,
1832460ea898SWenjing Liu 		struct dc_plane_state *plane_state,
1833460ea898SWenjing Liu 		struct dc_state *context)
1834460ea898SWenjing Liu {
1835460ea898SWenjing Liu 	struct pipe_ctx *opp_head_pipe = otg_master_pipe;
1836460ea898SWenjing Liu 
1837460ea898SWenjing Liu 	while (opp_head_pipe) {
1838460ea898SWenjing Liu 		if (opp_head_pipe->plane_state) {
1839460ea898SWenjing Liu 			ASSERT(0);
1840460ea898SWenjing Liu 			return false;
1841460ea898SWenjing Liu 		}
1842460ea898SWenjing Liu 		opp_head_pipe->plane_state = plane_state;
1843460ea898SWenjing Liu 		opp_head_pipe = opp_head_pipe->next_odm_pipe;
1844460ea898SWenjing Liu 	}
1845460ea898SWenjing Liu 
1846460ea898SWenjing Liu 	return true;
1847460ea898SWenjing Liu }
1848460ea898SWenjing Liu 
insert_secondary_dpp_pipe_with_plane(struct pipe_ctx * opp_head_pipe,struct pipe_ctx * sec_pipe,struct dc_plane_state * plane_state)1849460ea898SWenjing Liu static void insert_secondary_dpp_pipe_with_plane(struct pipe_ctx *opp_head_pipe,
1850460ea898SWenjing Liu 		struct pipe_ctx *sec_pipe, struct dc_plane_state *plane_state)
1851460ea898SWenjing Liu {
1852460ea898SWenjing Liu 	struct pipe_ctx *tail_pipe = get_tail_pipe(opp_head_pipe);
1853460ea898SWenjing Liu 
1854460ea898SWenjing Liu 	tail_pipe->bottom_pipe = sec_pipe;
1855460ea898SWenjing Liu 	sec_pipe->top_pipe = tail_pipe;
1856460ea898SWenjing Liu 	if (tail_pipe->prev_odm_pipe) {
1857460ea898SWenjing Liu 		ASSERT(tail_pipe->prev_odm_pipe->bottom_pipe);
1858460ea898SWenjing Liu 		sec_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe;
1859460ea898SWenjing Liu 		tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = sec_pipe;
1860460ea898SWenjing Liu 	}
1861460ea898SWenjing Liu 	sec_pipe->plane_state = plane_state;
1862460ea898SWenjing Liu }
1863460ea898SWenjing Liu 
1864460ea898SWenjing Liu /* for each opp head pipe of an otg master pipe, acquire a secondary dpp pipe
1865460ea898SWenjing Liu  * and add the plane. So the plane is added to all MPC blend trees associated
1866460ea898SWenjing Liu  * with the otg master pipe.
1867460ea898SWenjing Liu  */
acquire_secondary_dpp_pipes_and_add_plane(struct pipe_ctx * otg_master_pipe,struct dc_plane_state * plane_state,struct dc_state * new_ctx,struct dc_state * cur_ctx,struct resource_pool * pool)1868460ea898SWenjing Liu static bool acquire_secondary_dpp_pipes_and_add_plane(
1869460ea898SWenjing Liu 		struct pipe_ctx *otg_master_pipe,
1870460ea898SWenjing Liu 		struct dc_plane_state *plane_state,
1871460ea898SWenjing Liu 		struct dc_state *new_ctx,
1872460ea898SWenjing Liu 		struct dc_state *cur_ctx,
1873460ea898SWenjing Liu 		struct resource_pool *pool)
1874460ea898SWenjing Liu {
1875460ea898SWenjing Liu 	struct pipe_ctx *opp_head_pipe, *sec_pipe;
1876460ea898SWenjing Liu 
1877198f0e89SWenjing Liu 	if (!pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe)
1878460ea898SWenjing Liu 		return false;
1879460ea898SWenjing Liu 
1880460ea898SWenjing Liu 	opp_head_pipe = otg_master_pipe;
1881460ea898SWenjing Liu 	while (opp_head_pipe) {
1882198f0e89SWenjing Liu 		sec_pipe = pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe(
1883460ea898SWenjing Liu 				cur_ctx,
1884460ea898SWenjing Liu 				new_ctx,
1885460ea898SWenjing Liu 				pool,
1886460ea898SWenjing Liu 				opp_head_pipe);
1887460ea898SWenjing Liu 		if (!sec_pipe) {
1888460ea898SWenjing Liu 			/* try tearing down MPCC combine */
1889460ea898SWenjing Liu 			int pipe_idx = acquire_first_split_pipe(
1890460ea898SWenjing Liu 					&new_ctx->res_ctx, pool,
1891460ea898SWenjing Liu 					otg_master_pipe->stream);
1892460ea898SWenjing Liu 
1893460ea898SWenjing Liu 			if (pipe_idx >= 0)
1894460ea898SWenjing Liu 				sec_pipe = &new_ctx->res_ctx.pipe_ctx[pipe_idx];
1895460ea898SWenjing Liu 		}
1896460ea898SWenjing Liu 
1897460ea898SWenjing Liu 		if (!sec_pipe)
1898460ea898SWenjing Liu 			return false;
1899460ea898SWenjing Liu 
1900460ea898SWenjing Liu 		insert_secondary_dpp_pipe_with_plane(opp_head_pipe, sec_pipe,
1901460ea898SWenjing Liu 				plane_state);
1902460ea898SWenjing Liu 		opp_head_pipe = opp_head_pipe->next_odm_pipe;
1903460ea898SWenjing Liu 	}
1904460ea898SWenjing Liu 	return true;
1905460ea898SWenjing Liu }
1906460ea898SWenjing Liu 
dc_add_plane_to_context(const struct dc * dc,struct dc_stream_state * stream,struct dc_plane_state * plane_state,struct dc_state * context)190719f89e23SAndrey Grodzovsky bool dc_add_plane_to_context(
190819f89e23SAndrey Grodzovsky 		const struct dc *dc,
19090971c40eSHarry Wentland 		struct dc_stream_state *stream,
191019f89e23SAndrey Grodzovsky 		struct dc_plane_state *plane_state,
1911608ac7bbSJerry Zuo 		struct dc_state *context)
19124562236bSHarry Wentland {
191319f89e23SAndrey Grodzovsky 	struct resource_pool *pool = dc->res_pool;
1914460ea898SWenjing Liu 	struct pipe_ctx *otg_master_pipe;
1915ab2541b6SAric Cyr 	struct dc_stream_status *stream_status = NULL;
1916460ea898SWenjing Liu 	bool added = false;
19174562236bSHarry Wentland 
1918460ea898SWenjing Liu 	stream_status = dc_stream_get_status_from_state(context, stream);
1919ab2541b6SAric Cyr 	if (stream_status == NULL) {
192019f89e23SAndrey Grodzovsky 		dm_error("Existing stream not found; failed to attach surface!\n");
1921460ea898SWenjing Liu 		goto out;
1922460ea898SWenjing Liu 	} else if (stream_status->plane_count == MAX_SURFACE_NUM) {
192319f89e23SAndrey Grodzovsky 		dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
192419f89e23SAndrey Grodzovsky 				plane_state, MAX_SURFACE_NUM);
1925460ea898SWenjing Liu 		goto out;
192619f89e23SAndrey Grodzovsky 	}
192719f89e23SAndrey Grodzovsky 
192853f32880SWenjing Liu 	otg_master_pipe = resource_get_otg_master_for_stream(
1929460ea898SWenjing Liu 			&context->res_ctx, stream);
1930460ea898SWenjing Liu 	if (otg_master_pipe->plane_state == NULL)
1931460ea898SWenjing Liu 		added = add_plane_to_opp_head_pipes(otg_master_pipe,
1932460ea898SWenjing Liu 				plane_state, context);
1933460ea898SWenjing Liu 	else
1934460ea898SWenjing Liu 		added = acquire_secondary_dpp_pipes_and_add_plane(
1935460ea898SWenjing Liu 				otg_master_pipe, plane_state, context,
1936460ea898SWenjing Liu 				dc->current_state, pool);
1937460ea898SWenjing Liu 	if (added) {
1938460ea898SWenjing Liu 		stream_status->plane_states[stream_status->plane_count] =
1939460ea898SWenjing Liu 				plane_state;
194019f89e23SAndrey Grodzovsky 		stream_status->plane_count++;
1941460ea898SWenjing Liu 		dc_plane_state_retain(plane_state);
1942460ea898SWenjing Liu 	}
19434562236bSHarry Wentland 
1944460ea898SWenjing Liu out:
1945460ea898SWenjing Liu 	return added;
19464562236bSHarry Wentland }
19474562236bSHarry Wentland 
dc_remove_plane_from_context(const struct dc * dc,struct dc_stream_state * stream,struct dc_plane_state * plane_state,struct dc_state * context)194819f89e23SAndrey Grodzovsky bool dc_remove_plane_from_context(
194919f89e23SAndrey Grodzovsky 		const struct dc *dc,
195019f89e23SAndrey Grodzovsky 		struct dc_stream_state *stream,
195119f89e23SAndrey Grodzovsky 		struct dc_plane_state *plane_state,
1952608ac7bbSJerry Zuo 		struct dc_state *context)
195319f89e23SAndrey Grodzovsky {
195419f89e23SAndrey Grodzovsky 	int i;
195519f89e23SAndrey Grodzovsky 	struct dc_stream_status *stream_status = NULL;
195619f89e23SAndrey Grodzovsky 	struct resource_pool *pool = dc->res_pool;
195719f89e23SAndrey Grodzovsky 
195872529b68SAurabindo Pillai 	if (!plane_state)
195972529b68SAurabindo Pillai 		return true;
196072529b68SAurabindo Pillai 
196119f89e23SAndrey Grodzovsky 	for (i = 0; i < context->stream_count; i++)
196219f89e23SAndrey Grodzovsky 		if (context->streams[i] == stream) {
196319f89e23SAndrey Grodzovsky 			stream_status = &context->stream_status[i];
196419f89e23SAndrey Grodzovsky 			break;
196519f89e23SAndrey Grodzovsky 		}
196619f89e23SAndrey Grodzovsky 
196719f89e23SAndrey Grodzovsky 	if (stream_status == NULL) {
196819f89e23SAndrey Grodzovsky 		dm_error("Existing stream not found; failed to remove plane.\n");
196919f89e23SAndrey Grodzovsky 		return false;
197019f89e23SAndrey Grodzovsky 	}
197119f89e23SAndrey Grodzovsky 
197219f89e23SAndrey Grodzovsky 	/* release pipe for plane*/
197319f89e23SAndrey Grodzovsky 	for (i = pool->pipe_count - 1; i >= 0; i--) {
19746ffaa6fcSDmytro Laktyushkin 		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
197519f89e23SAndrey Grodzovsky 
19766ffaa6fcSDmytro Laktyushkin 		if (pipe_ctx->plane_state == plane_state) {
197719f89e23SAndrey Grodzovsky 			if (pipe_ctx->top_pipe)
197819f89e23SAndrey Grodzovsky 				pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
197919f89e23SAndrey Grodzovsky 
198019f89e23SAndrey Grodzovsky 			/* Second condition is to avoid setting NULL to top pipe
198119f89e23SAndrey Grodzovsky 			 * of tail pipe making it look like head pipe in subsequent
198219f89e23SAndrey Grodzovsky 			 * deletes
198319f89e23SAndrey Grodzovsky 			 */
198419f89e23SAndrey Grodzovsky 			if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe)
198519f89e23SAndrey Grodzovsky 				pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
198619f89e23SAndrey Grodzovsky 
198719f89e23SAndrey Grodzovsky 			/*
198819f89e23SAndrey Grodzovsky 			 * For head pipe detach surfaces from pipe for tail
198919f89e23SAndrey Grodzovsky 			 * pipe just zero it out
199019f89e23SAndrey Grodzovsky 			 */
1991b1f6d01cSDmytro Laktyushkin 			if (!pipe_ctx->top_pipe)
199219f89e23SAndrey Grodzovsky 				pipe_ctx->plane_state = NULL;
1993b1f6d01cSDmytro Laktyushkin 			else
199419f89e23SAndrey Grodzovsky 				memset(pipe_ctx, 0, sizeof(*pipe_ctx));
199519f89e23SAndrey Grodzovsky 		}
199619f89e23SAndrey Grodzovsky 	}
199719f89e23SAndrey Grodzovsky 
199819f89e23SAndrey Grodzovsky 
199919f89e23SAndrey Grodzovsky 	for (i = 0; i < stream_status->plane_count; i++) {
200019f89e23SAndrey Grodzovsky 		if (stream_status->plane_states[i] == plane_state) {
200119f89e23SAndrey Grodzovsky 			dc_plane_state_release(stream_status->plane_states[i]);
200219f89e23SAndrey Grodzovsky 			break;
200319f89e23SAndrey Grodzovsky 		}
200419f89e23SAndrey Grodzovsky 	}
200519f89e23SAndrey Grodzovsky 
200619f89e23SAndrey Grodzovsky 	if (i == stream_status->plane_count) {
200719f89e23SAndrey Grodzovsky 		dm_error("Existing plane_state not found; failed to detach it!\n");
200819f89e23SAndrey Grodzovsky 		return false;
200919f89e23SAndrey Grodzovsky 	}
201019f89e23SAndrey Grodzovsky 
201119f89e23SAndrey Grodzovsky 	stream_status->plane_count--;
201219f89e23SAndrey Grodzovsky 
2013abb4986eSAndrew Jiang 	/* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */
2014abb4986eSAndrew Jiang 	for (; i < stream_status->plane_count; i++)
201519f89e23SAndrey Grodzovsky 		stream_status->plane_states[i] = stream_status->plane_states[i + 1];
201619f89e23SAndrey Grodzovsky 
201719f89e23SAndrey Grodzovsky 	stream_status->plane_states[stream_status->plane_count] = NULL;
201819f89e23SAndrey Grodzovsky 
201919f89e23SAndrey Grodzovsky 	return true;
202019f89e23SAndrey Grodzovsky }
202119f89e23SAndrey Grodzovsky 
20226a0114e0SRodrigo Siqueira /**
20236a0114e0SRodrigo Siqueira  * dc_rem_all_planes_for_stream - Remove planes attached to the target stream.
20246a0114e0SRodrigo Siqueira  *
20256a0114e0SRodrigo Siqueira  * @dc: Current dc state.
20266a0114e0SRodrigo Siqueira  * @stream: Target stream, which we want to remove the attached plans.
20276a0114e0SRodrigo Siqueira  * @context: New context.
20286a0114e0SRodrigo Siqueira  *
20296a0114e0SRodrigo Siqueira  * Return:
20306a0114e0SRodrigo Siqueira  * Return true if DC was able to remove all planes from the target
20316a0114e0SRodrigo Siqueira  * stream, otherwise, return false.
20326a0114e0SRodrigo Siqueira  */
dc_rem_all_planes_for_stream(const struct dc * dc,struct dc_stream_state * stream,struct dc_state * context)203319f89e23SAndrey Grodzovsky bool dc_rem_all_planes_for_stream(
203419f89e23SAndrey Grodzovsky 		const struct dc *dc,
203519f89e23SAndrey Grodzovsky 		struct dc_stream_state *stream,
2036608ac7bbSJerry Zuo 		struct dc_state *context)
203719f89e23SAndrey Grodzovsky {
203819f89e23SAndrey Grodzovsky 	int i, old_plane_count;
203919f89e23SAndrey Grodzovsky 	struct dc_stream_status *stream_status = NULL;
204019f89e23SAndrey Grodzovsky 	struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
204119f89e23SAndrey Grodzovsky 
204219f89e23SAndrey Grodzovsky 	for (i = 0; i < context->stream_count; i++)
204319f89e23SAndrey Grodzovsky 			if (context->streams[i] == stream) {
204419f89e23SAndrey Grodzovsky 				stream_status = &context->stream_status[i];
204519f89e23SAndrey Grodzovsky 				break;
204619f89e23SAndrey Grodzovsky 			}
204719f89e23SAndrey Grodzovsky 
204819f89e23SAndrey Grodzovsky 	if (stream_status == NULL) {
204919f89e23SAndrey Grodzovsky 		dm_error("Existing stream %p not found!\n", stream);
205019f89e23SAndrey Grodzovsky 		return false;
205119f89e23SAndrey Grodzovsky 	}
205219f89e23SAndrey Grodzovsky 
205319f89e23SAndrey Grodzovsky 	old_plane_count = stream_status->plane_count;
205419f89e23SAndrey Grodzovsky 
205519f89e23SAndrey Grodzovsky 	for (i = 0; i < old_plane_count; i++)
205619f89e23SAndrey Grodzovsky 		del_planes[i] = stream_status->plane_states[i];
205719f89e23SAndrey Grodzovsky 
205819f89e23SAndrey Grodzovsky 	for (i = 0; i < old_plane_count; i++)
205919f89e23SAndrey Grodzovsky 		if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context))
206019f89e23SAndrey Grodzovsky 			return false;
206119f89e23SAndrey Grodzovsky 
206219f89e23SAndrey Grodzovsky 	return true;
206319f89e23SAndrey Grodzovsky }
206419f89e23SAndrey Grodzovsky 
add_all_planes_for_stream(const struct dc * dc,struct dc_stream_state * stream,const struct dc_validation_set set[],int set_count,struct dc_state * context)206519f89e23SAndrey Grodzovsky static bool add_all_planes_for_stream(
206619f89e23SAndrey Grodzovsky 		const struct dc *dc,
206719f89e23SAndrey Grodzovsky 		struct dc_stream_state *stream,
206819f89e23SAndrey Grodzovsky 		const struct dc_validation_set set[],
206919f89e23SAndrey Grodzovsky 		int set_count,
2070608ac7bbSJerry Zuo 		struct dc_state *context)
207119f89e23SAndrey Grodzovsky {
207219f89e23SAndrey Grodzovsky 	int i, j;
207319f89e23SAndrey Grodzovsky 
207419f89e23SAndrey Grodzovsky 	for (i = 0; i < set_count; i++)
207519f89e23SAndrey Grodzovsky 		if (set[i].stream == stream)
207619f89e23SAndrey Grodzovsky 			break;
207719f89e23SAndrey Grodzovsky 
207819f89e23SAndrey Grodzovsky 	if (i == set_count) {
207919f89e23SAndrey Grodzovsky 		dm_error("Stream %p not found in set!\n", stream);
208019f89e23SAndrey Grodzovsky 		return false;
208119f89e23SAndrey Grodzovsky 	}
208219f89e23SAndrey Grodzovsky 
208319f89e23SAndrey Grodzovsky 	for (j = 0; j < set[i].plane_count; j++)
208419f89e23SAndrey Grodzovsky 		if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context))
208519f89e23SAndrey Grodzovsky 			return false;
208619f89e23SAndrey Grodzovsky 
208719f89e23SAndrey Grodzovsky 	return true;
208819f89e23SAndrey Grodzovsky }
208919f89e23SAndrey Grodzovsky 
dc_add_all_planes_for_stream(const struct dc * dc,struct dc_stream_state * stream,struct dc_plane_state * const * plane_states,int plane_count,struct dc_state * context)209019f89e23SAndrey Grodzovsky bool dc_add_all_planes_for_stream(
209119f89e23SAndrey Grodzovsky 		const struct dc *dc,
209219f89e23SAndrey Grodzovsky 		struct dc_stream_state *stream,
209319f89e23SAndrey Grodzovsky 		struct dc_plane_state * const *plane_states,
209419f89e23SAndrey Grodzovsky 		int plane_count,
2095608ac7bbSJerry Zuo 		struct dc_state *context)
209619f89e23SAndrey Grodzovsky {
209719f89e23SAndrey Grodzovsky 	struct dc_validation_set set;
209819f89e23SAndrey Grodzovsky 	int i;
209919f89e23SAndrey Grodzovsky 
210019f89e23SAndrey Grodzovsky 	set.stream = stream;
210119f89e23SAndrey Grodzovsky 	set.plane_count = plane_count;
210219f89e23SAndrey Grodzovsky 
210319f89e23SAndrey Grodzovsky 	for (i = 0; i < plane_count; i++)
210419f89e23SAndrey Grodzovsky 		set.plane_states[i] = plane_states[i];
210519f89e23SAndrey Grodzovsky 
210619f89e23SAndrey Grodzovsky 	return add_all_planes_for_stream(dc, stream, &set, 1, context);
210719f89e23SAndrey Grodzovsky }
210819f89e23SAndrey Grodzovsky 
dc_is_timing_changed(struct dc_stream_state * cur_stream,struct dc_stream_state * new_stream)21093306ba4bSArnd Bergmann bool dc_is_timing_changed(struct dc_stream_state *cur_stream,
21100971c40eSHarry Wentland 		       struct dc_stream_state *new_stream)
21114562236bSHarry Wentland {
21124562236bSHarry Wentland 	if (cur_stream == NULL)
21134562236bSHarry Wentland 		return true;
21144562236bSHarry Wentland 
21154562236bSHarry Wentland 	/* If output color space is changed, need to reprogram info frames */
21164fa086b9SLeo (Sunpeng) Li 	if (cur_stream->output_color_space != new_stream->output_color_space)
21174562236bSHarry Wentland 		return true;
21184562236bSHarry Wentland 
21194562236bSHarry Wentland 	return memcmp(
21204fa086b9SLeo (Sunpeng) Li 		&cur_stream->timing,
21214fa086b9SLeo (Sunpeng) Li 		&new_stream->timing,
21224562236bSHarry Wentland 		sizeof(struct dc_crtc_timing)) != 0;
21234562236bSHarry Wentland }
21244562236bSHarry Wentland 
are_stream_backends_same(struct dc_stream_state * stream_a,struct dc_stream_state * stream_b)21254562236bSHarry Wentland static bool are_stream_backends_same(
21260971c40eSHarry Wentland 	struct dc_stream_state *stream_a, struct dc_stream_state *stream_b)
21274562236bSHarry Wentland {
21284562236bSHarry Wentland 	if (stream_a == stream_b)
21294562236bSHarry Wentland 		return true;
21304562236bSHarry Wentland 
21314562236bSHarry Wentland 	if (stream_a == NULL || stream_b == NULL)
21324562236bSHarry Wentland 		return false;
21334562236bSHarry Wentland 
21343306ba4bSArnd Bergmann 	if (dc_is_timing_changed(stream_a, stream_b))
21354562236bSHarry Wentland 		return false;
21364562236bSHarry Wentland 
2137047db281SDale Zhao 	if (stream_a->signal != stream_b->signal)
2138047db281SDale Zhao 		return false;
2139047db281SDale Zhao 
21401e7e86c4SSamson Tam 	if (stream_a->dpms_off != stream_b->dpms_off)
21411e7e86c4SSamson Tam 		return false;
21421e7e86c4SSamson Tam 
21434562236bSHarry Wentland 	return true;
21444562236bSHarry Wentland }
21454562236bSHarry Wentland 
2146625a15bfSLee Jones /*
21472119aa17SDavid Francis  * dc_is_stream_unchanged() - Compare two stream states for equivalence.
21482119aa17SDavid Francis  *
21492119aa17SDavid Francis  * Checks if there a difference between the two states
21502119aa17SDavid Francis  * that would require a mode change.
21512119aa17SDavid Francis  *
21522119aa17SDavid Francis  * Does not compare cursor position or attributes.
21532119aa17SDavid Francis  */
dc_is_stream_unchanged(struct dc_stream_state * old_stream,struct dc_stream_state * stream)2154d54d29dbSBhawanpreet Lakha bool dc_is_stream_unchanged(
21550971c40eSHarry Wentland 	struct dc_stream_state *old_stream, struct dc_stream_state *stream)
21564562236bSHarry Wentland {
21574562236bSHarry Wentland 
21584562236bSHarry Wentland 	if (!are_stream_backends_same(old_stream, stream))
21594562236bSHarry Wentland 		return false;
21604562236bSHarry Wentland 
21610460f9abSJun Lei 	if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param)
21620460f9abSJun Lei 		return false;
21630460f9abSJun Lei 
21645e8a71cfSCharlene Liu 	/*compare audio info*/
21655e8a71cfSCharlene Liu 	if (memcmp(&old_stream->audio_info, &stream->audio_info, sizeof(stream->audio_info)) != 0)
21669602044dSMustapha Ghaddar 		return false;
21679602044dSMustapha Ghaddar 
21684562236bSHarry Wentland 	return true;
21694562236bSHarry Wentland }
21704562236bSHarry Wentland 
2171625a15bfSLee Jones /*
21722119aa17SDavid Francis  * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams.
21732119aa17SDavid Francis  */
dc_is_stream_scaling_unchanged(struct dc_stream_state * old_stream,struct dc_stream_state * stream)217417ce8a69SRoman Li bool dc_is_stream_scaling_unchanged(struct dc_stream_state *old_stream,
217517ce8a69SRoman Li 				    struct dc_stream_state *stream)
21769a5d9c48SLeo (Sunpeng) Li {
21779a5d9c48SLeo (Sunpeng) Li 	if (old_stream == stream)
21789a5d9c48SLeo (Sunpeng) Li 		return true;
21799a5d9c48SLeo (Sunpeng) Li 
21809a5d9c48SLeo (Sunpeng) Li 	if (old_stream == NULL || stream == NULL)
21819a5d9c48SLeo (Sunpeng) Li 		return false;
21829a5d9c48SLeo (Sunpeng) Li 
21839a5d9c48SLeo (Sunpeng) Li 	if (memcmp(&old_stream->src,
21849a5d9c48SLeo (Sunpeng) Li 			&stream->src,
21859a5d9c48SLeo (Sunpeng) Li 			sizeof(struct rect)) != 0)
21869a5d9c48SLeo (Sunpeng) Li 		return false;
21879a5d9c48SLeo (Sunpeng) Li 
21889a5d9c48SLeo (Sunpeng) Li 	if (memcmp(&old_stream->dst,
21899a5d9c48SLeo (Sunpeng) Li 			&stream->dst,
21909a5d9c48SLeo (Sunpeng) Li 			sizeof(struct rect)) != 0)
21919a5d9c48SLeo (Sunpeng) Li 		return false;
21929a5d9c48SLeo (Sunpeng) Li 
21939a5d9c48SLeo (Sunpeng) Li 	return true;
21949a5d9c48SLeo (Sunpeng) Li }
21959a5d9c48SLeo (Sunpeng) Li 
update_stream_engine_usage(struct resource_context * res_ctx,const struct resource_pool * pool,struct stream_encoder * stream_enc,bool acquired)21961dc90497SAndrey Grodzovsky static void update_stream_engine_usage(
21974562236bSHarry Wentland 		struct resource_context *res_ctx,
2198a2b8659dSTony Cheng 		const struct resource_pool *pool,
21991dc90497SAndrey Grodzovsky 		struct stream_encoder *stream_enc,
22001dc90497SAndrey Grodzovsky 		bool acquired)
22014562236bSHarry Wentland {
22024562236bSHarry Wentland 	int i;
22034562236bSHarry Wentland 
2204a2b8659dSTony Cheng 	for (i = 0; i < pool->stream_enc_count; i++) {
2205a2b8659dSTony Cheng 		if (pool->stream_enc[i] == stream_enc)
22061dc90497SAndrey Grodzovsky 			res_ctx->is_stream_enc_acquired[i] = acquired;
22074562236bSHarry Wentland 	}
22084562236bSHarry Wentland }
22094562236bSHarry Wentland 
update_hpo_dp_stream_engine_usage(struct resource_context * res_ctx,const struct resource_pool * pool,struct hpo_dp_stream_encoder * hpo_dp_stream_enc,bool acquired)2210f01ee019SFangzhi Zuo static void update_hpo_dp_stream_engine_usage(
2211f01ee019SFangzhi Zuo 		struct resource_context *res_ctx,
2212f01ee019SFangzhi Zuo 		const struct resource_pool *pool,
2213f01ee019SFangzhi Zuo 		struct hpo_dp_stream_encoder *hpo_dp_stream_enc,
2214f01ee019SFangzhi Zuo 		bool acquired)
2215f01ee019SFangzhi Zuo {
2216f01ee019SFangzhi Zuo 	int i;
2217f01ee019SFangzhi Zuo 
2218f01ee019SFangzhi Zuo 	for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
2219f01ee019SFangzhi Zuo 		if (pool->hpo_dp_stream_enc[i] == hpo_dp_stream_enc)
2220f01ee019SFangzhi Zuo 			res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired;
2221f01ee019SFangzhi Zuo 	}
2222f01ee019SFangzhi Zuo }
22236dd8931bSWenjing Liu 
find_acquired_hpo_dp_link_enc_for_link(const struct resource_context * res_ctx,const struct dc_link * link)22246dd8931bSWenjing Liu static inline int find_acquired_hpo_dp_link_enc_for_link(
22256dd8931bSWenjing Liu 		const struct resource_context *res_ctx,
22266dd8931bSWenjing Liu 		const struct dc_link *link)
22276dd8931bSWenjing Liu {
22286dd8931bSWenjing Liu 	int i;
22296dd8931bSWenjing Liu 
22306dd8931bSWenjing Liu 	for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_to_link_idx); i++)
22316dd8931bSWenjing Liu 		if (res_ctx->hpo_dp_link_enc_ref_cnts[i] > 0 &&
22326dd8931bSWenjing Liu 				res_ctx->hpo_dp_link_enc_to_link_idx[i] == link->link_index)
22336dd8931bSWenjing Liu 			return i;
22346dd8931bSWenjing Liu 
22356dd8931bSWenjing Liu 	return -1;
22366dd8931bSWenjing Liu }
22376dd8931bSWenjing Liu 
find_free_hpo_dp_link_enc(const struct resource_context * res_ctx,const struct resource_pool * pool)22386dd8931bSWenjing Liu static inline int find_free_hpo_dp_link_enc(const struct resource_context *res_ctx,
22396dd8931bSWenjing Liu 		const struct resource_pool *pool)
22406dd8931bSWenjing Liu {
22416dd8931bSWenjing Liu 	int i;
22426dd8931bSWenjing Liu 
22436dd8931bSWenjing Liu 	for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts); i++)
22446dd8931bSWenjing Liu 		if (res_ctx->hpo_dp_link_enc_ref_cnts[i] == 0)
22456dd8931bSWenjing Liu 			break;
22466dd8931bSWenjing Liu 
22476dd8931bSWenjing Liu 	return (i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts) &&
22486dd8931bSWenjing Liu 			i < pool->hpo_dp_link_enc_count) ? i : -1;
22496dd8931bSWenjing Liu }
22506dd8931bSWenjing Liu 
acquire_hpo_dp_link_enc(struct resource_context * res_ctx,unsigned int link_index,int enc_index)22516dd8931bSWenjing Liu static inline void acquire_hpo_dp_link_enc(
22526dd8931bSWenjing Liu 		struct resource_context *res_ctx,
22536dd8931bSWenjing Liu 		unsigned int link_index,
22546dd8931bSWenjing Liu 		int enc_index)
22556dd8931bSWenjing Liu {
22566dd8931bSWenjing Liu 	res_ctx->hpo_dp_link_enc_to_link_idx[enc_index] = link_index;
22576dd8931bSWenjing Liu 	res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] = 1;
22586dd8931bSWenjing Liu }
22596dd8931bSWenjing Liu 
retain_hpo_dp_link_enc(struct resource_context * res_ctx,int enc_index)22606dd8931bSWenjing Liu static inline void retain_hpo_dp_link_enc(
22616dd8931bSWenjing Liu 		struct resource_context *res_ctx,
22626dd8931bSWenjing Liu 		int enc_index)
22636dd8931bSWenjing Liu {
22646dd8931bSWenjing Liu 	res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]++;
22656dd8931bSWenjing Liu }
22666dd8931bSWenjing Liu 
release_hpo_dp_link_enc(struct resource_context * res_ctx,int enc_index)22676dd8931bSWenjing Liu static inline void release_hpo_dp_link_enc(
22686dd8931bSWenjing Liu 		struct resource_context *res_ctx,
22696dd8931bSWenjing Liu 		int enc_index)
22706dd8931bSWenjing Liu {
22716dd8931bSWenjing Liu 	ASSERT(res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] > 0);
22726dd8931bSWenjing Liu 	res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]--;
22736dd8931bSWenjing Liu }
22746dd8931bSWenjing Liu 
add_hpo_dp_link_enc_to_ctx(struct resource_context * res_ctx,const struct resource_pool * pool,struct pipe_ctx * pipe_ctx,struct dc_stream_state * stream)22756dd8931bSWenjing Liu static bool add_hpo_dp_link_enc_to_ctx(struct resource_context *res_ctx,
22766dd8931bSWenjing Liu 		const struct resource_pool *pool,
22776dd8931bSWenjing Liu 		struct pipe_ctx *pipe_ctx,
22786dd8931bSWenjing Liu 		struct dc_stream_state *stream)
22796dd8931bSWenjing Liu {
22806dd8931bSWenjing Liu 	int enc_index;
22816dd8931bSWenjing Liu 
22826dd8931bSWenjing Liu 	enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link);
22836dd8931bSWenjing Liu 
22846dd8931bSWenjing Liu 	if (enc_index >= 0) {
22856dd8931bSWenjing Liu 		retain_hpo_dp_link_enc(res_ctx, enc_index);
22866dd8931bSWenjing Liu 	} else {
22876dd8931bSWenjing Liu 		enc_index = find_free_hpo_dp_link_enc(res_ctx, pool);
22886dd8931bSWenjing Liu 		if (enc_index >= 0)
22896dd8931bSWenjing Liu 			acquire_hpo_dp_link_enc(res_ctx, stream->link->link_index, enc_index);
22906dd8931bSWenjing Liu 	}
22916dd8931bSWenjing Liu 
22926dd8931bSWenjing Liu 	if (enc_index >= 0)
22936dd8931bSWenjing Liu 		pipe_ctx->link_res.hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index];
22946dd8931bSWenjing Liu 
22956dd8931bSWenjing Liu 	return pipe_ctx->link_res.hpo_dp_link_enc != NULL;
22966dd8931bSWenjing Liu }
22976dd8931bSWenjing Liu 
remove_hpo_dp_link_enc_from_ctx(struct resource_context * res_ctx,struct pipe_ctx * pipe_ctx,struct dc_stream_state * stream)22986dd8931bSWenjing Liu static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
22996dd8931bSWenjing Liu 		struct pipe_ctx *pipe_ctx,
23006dd8931bSWenjing Liu 		struct dc_stream_state *stream)
23016dd8931bSWenjing Liu {
23026dd8931bSWenjing Liu 	int enc_index;
23036dd8931bSWenjing Liu 
23046dd8931bSWenjing Liu 	enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link);
23056dd8931bSWenjing Liu 
23066dd8931bSWenjing Liu 	if (enc_index >= 0) {
23076dd8931bSWenjing Liu 		release_hpo_dp_link_enc(res_ctx, enc_index);
23086dd8931bSWenjing Liu 		pipe_ctx->link_res.hpo_dp_link_enc = NULL;
23096dd8931bSWenjing Liu 	}
23106dd8931bSWenjing Liu }
2311f01ee019SFangzhi Zuo 
23124562236bSHarry Wentland /* TODO: release audio object */
update_audio_usage(struct resource_context * res_ctx,const struct resource_pool * pool,struct audio * audio,bool acquired)23134176664bSCharlene Liu void update_audio_usage(
23144562236bSHarry Wentland 		struct resource_context *res_ctx,
2315a2b8659dSTony Cheng 		const struct resource_pool *pool,
23161dc90497SAndrey Grodzovsky 		struct audio *audio,
23171dc90497SAndrey Grodzovsky 		bool acquired)
23184562236bSHarry Wentland {
23194562236bSHarry Wentland 	int i;
2320a2b8659dSTony Cheng 	for (i = 0; i < pool->audio_count; i++) {
2321a2b8659dSTony Cheng 		if (pool->audios[i] == audio)
23221dc90497SAndrey Grodzovsky 			res_ctx->is_audio_acquired[i] = acquired;
23234562236bSHarry Wentland 	}
23244562236bSHarry Wentland }
23254562236bSHarry Wentland 
acquire_first_free_pipe(struct resource_context * res_ctx,const struct resource_pool * pool,struct dc_stream_state * stream)23264562236bSHarry Wentland static int acquire_first_free_pipe(
23274562236bSHarry Wentland 		struct resource_context *res_ctx,
2328a2b8659dSTony Cheng 		const struct resource_pool *pool,
23290971c40eSHarry Wentland 		struct dc_stream_state *stream)
23304562236bSHarry Wentland {
23314562236bSHarry Wentland 	int i;
23324562236bSHarry Wentland 
2333a2b8659dSTony Cheng 	for (i = 0; i < pool->pipe_count; i++) {
23344562236bSHarry Wentland 		if (!res_ctx->pipe_ctx[i].stream) {
23354562236bSHarry Wentland 			struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
23364562236bSHarry Wentland 
23376b670fa9SHarry Wentland 			pipe_ctx->stream_res.tg = pool->timing_generators[i];
233886a66c4eSHarry Wentland 			pipe_ctx->plane_res.mi = pool->mis[i];
23398feabd03SYue Hin Lau 			pipe_ctx->plane_res.hubp = pool->hubps[i];
234086a66c4eSHarry Wentland 			pipe_ctx->plane_res.ipp = pool->ipps[i];
234186a66c4eSHarry Wentland 			pipe_ctx->plane_res.xfm = pool->transforms[i];
2342d94585a0SYue Hin Lau 			pipe_ctx->plane_res.dpp = pool->dpps[i];
2343a6a6cb34SHarry Wentland 			pipe_ctx->stream_res.opp = pool->opps[i];
2344bc373a89SRoman Li 			if (pool->dpps[i])
2345e07f541fSYongqiang Sun 				pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst;
23464562236bSHarry Wentland 			pipe_ctx->pipe_idx = i;
23474562236bSHarry Wentland 
2348c1127df9SEric Bernstein 			if (i >= pool->timing_generator_count) {
2349c1127df9SEric Bernstein 				int tg_inst = pool->timing_generator_count - 1;
2350c1127df9SEric Bernstein 
2351c1127df9SEric Bernstein 				pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
2352c1127df9SEric Bernstein 				pipe_ctx->stream_res.opp = pool->opps[tg_inst];
2353c1127df9SEric Bernstein 			}
2354ff5ef992SAlex Deucher 
23554562236bSHarry Wentland 			pipe_ctx->stream = stream;
23564562236bSHarry Wentland 			return i;
23574562236bSHarry Wentland 		}
23584562236bSHarry Wentland 	}
23594562236bSHarry Wentland 	return -1;
23604562236bSHarry Wentland }
23614562236bSHarry Wentland 
find_first_free_match_hpo_dp_stream_enc_for_link(struct resource_context * res_ctx,const struct resource_pool * pool,struct dc_stream_state * stream)2362f01ee019SFangzhi Zuo static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for_link(
2363f01ee019SFangzhi Zuo 		struct resource_context *res_ctx,
2364f01ee019SFangzhi Zuo 		const struct resource_pool *pool,
2365f01ee019SFangzhi Zuo 		struct dc_stream_state *stream)
2366f01ee019SFangzhi Zuo {
2367f01ee019SFangzhi Zuo 	int i;
2368f01ee019SFangzhi Zuo 
2369f01ee019SFangzhi Zuo 	for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
2370f01ee019SFangzhi Zuo 		if (!res_ctx->is_hpo_dp_stream_enc_acquired[i] &&
2371f01ee019SFangzhi Zuo 				pool->hpo_dp_stream_enc[i]) {
2372f01ee019SFangzhi Zuo 
2373f01ee019SFangzhi Zuo 			return pool->hpo_dp_stream_enc[i];
2374f01ee019SFangzhi Zuo 		}
2375f01ee019SFangzhi Zuo 	}
2376f01ee019SFangzhi Zuo 
2377f01ee019SFangzhi Zuo 	return NULL;
2378f01ee019SFangzhi Zuo }
2379f01ee019SFangzhi Zuo 
find_first_free_audio(struct resource_context * res_ctx,const struct resource_pool * pool,enum engine_id id,enum dce_version dc_version)2380a2b8659dSTony Cheng static struct audio *find_first_free_audio(
2381a2b8659dSTony Cheng 		struct resource_context *res_ctx,
2382cfb071f7SCharlene Liu 		const struct resource_pool *pool,
2383f24b0522SPaul Hsieh 		enum engine_id id,
2384f24b0522SPaul Hsieh 		enum dce_version dc_version)
23854562236bSHarry Wentland {
2386b5a41620SCharlene Liu 	int i, available_audio_count;
2387b5a41620SCharlene Liu 
2388b5a41620SCharlene Liu 	available_audio_count = pool->audio_count;
2389b5a41620SCharlene Liu 
2390b5a41620SCharlene Liu 	for (i = 0; i < available_audio_count; i++) {
23914176664bSCharlene Liu 		if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) {
2392cfb071f7SCharlene Liu 			/*we have enough audio endpoint, find the matching inst*/
2393cfb071f7SCharlene Liu 			if (id != i)
2394cfb071f7SCharlene Liu 				continue;
2395a2b8659dSTony Cheng 			return pool->audios[i];
23964562236bSHarry Wentland 		}
23974562236bSHarry Wentland 	}
23985feb9f07STai Man 
23995feb9f07STai Man 	/* use engine id to find free audio */
2400b5a41620SCharlene Liu 	if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) {
24015feb9f07STai Man 		return pool->audios[id];
24025feb9f07STai Man 	}
240366bfd4fdSCharlene Liu 	/*not found the matching one, first come first serve*/
2404b5a41620SCharlene Liu 	for (i = 0; i < available_audio_count; i++) {
24054176664bSCharlene Liu 		if (res_ctx->is_audio_acquired[i] == false) {
24064176664bSCharlene Liu 			return pool->audios[i];
24074176664bSCharlene Liu 		}
24084176664bSCharlene Liu 	}
2409b83e1ba9SMagali Lemes 	return NULL;
24104562236bSHarry Wentland }
24114562236bSHarry Wentland 
2412625a15bfSLee Jones /*
24132119aa17SDavid Francis  * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state.
24142119aa17SDavid Francis  */
dc_add_stream_to_ctx(struct dc * dc,struct dc_state * new_ctx,struct dc_stream_state * stream)241513ab1b44SYongqiang Sun enum dc_status dc_add_stream_to_ctx(
24161dc90497SAndrey Grodzovsky 		struct dc *dc,
2417608ac7bbSJerry Zuo 		struct dc_state *new_ctx,
24181dc90497SAndrey Grodzovsky 		struct dc_stream_state *stream)
24191dc90497SAndrey Grodzovsky {
24201dc90497SAndrey Grodzovsky 	enum dc_status res;
2421eb9714a2SWenjing Liu 	DC_LOGGER_INIT(dc->ctx->logger);
24221dc90497SAndrey Grodzovsky 
2423ece4147fSKen Chalmers 	if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) {
2424eb9714a2SWenjing Liu 		DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream);
24251dc90497SAndrey Grodzovsky 		return DC_ERROR_UNEXPECTED;
24261dc90497SAndrey Grodzovsky 	}
24271dc90497SAndrey Grodzovsky 
24281dc90497SAndrey Grodzovsky 	new_ctx->streams[new_ctx->stream_count] = stream;
24291dc90497SAndrey Grodzovsky 	dc_stream_retain(stream);
24301dc90497SAndrey Grodzovsky 	new_ctx->stream_count++;
24311dc90497SAndrey Grodzovsky 
24321dc90497SAndrey Grodzovsky 	res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
24331dc90497SAndrey Grodzovsky 	if (res != DC_OK)
2434eb9714a2SWenjing Liu 		DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res);
24351dc90497SAndrey Grodzovsky 
243613ab1b44SYongqiang Sun 	return res;
24371dc90497SAndrey Grodzovsky }
24381dc90497SAndrey Grodzovsky 
2439625a15bfSLee Jones /*
24402119aa17SDavid Francis  * dc_remove_stream_from_ctx() - Remove a stream from a dc_state.
24412119aa17SDavid Francis  */
dc_remove_stream_from_ctx(struct dc * dc,struct dc_state * new_ctx,struct dc_stream_state * stream)244262c933f9SYongqiang Sun enum dc_status dc_remove_stream_from_ctx(
24431dc90497SAndrey Grodzovsky 			struct dc *dc,
2444608ac7bbSJerry Zuo 			struct dc_state *new_ctx,
24451dc90497SAndrey Grodzovsky 			struct dc_stream_state *stream)
24461dc90497SAndrey Grodzovsky {
244719f89e23SAndrey Grodzovsky 	int i;
24481dc90497SAndrey Grodzovsky 	struct dc_context *dc_ctx = dc->ctx;
244953f32880SWenjing Liu 	struct pipe_ctx *del_pipe = resource_get_otg_master_for_stream(&new_ctx->res_ctx, stream);
245022498036SDmytro Laktyushkin 	struct pipe_ctx *odm_pipe;
245122498036SDmytro Laktyushkin 
245222498036SDmytro Laktyushkin 	if (!del_pipe) {
245322498036SDmytro Laktyushkin 		DC_ERROR("Pipe not found for stream %p !\n", stream);
245422498036SDmytro Laktyushkin 		return DC_ERROR_UNEXPECTED;
245522498036SDmytro Laktyushkin 	}
245622498036SDmytro Laktyushkin 
245722498036SDmytro Laktyushkin 	odm_pipe = del_pipe->next_odm_pipe;
24581dc90497SAndrey Grodzovsky 
245919f89e23SAndrey Grodzovsky 	/* Release primary pipe */
246019f89e23SAndrey Grodzovsky 	ASSERT(del_pipe->stream_res.stream_enc);
24611dc90497SAndrey Grodzovsky 	update_stream_engine_usage(
24621dc90497SAndrey Grodzovsky 			&new_ctx->res_ctx,
24631dc90497SAndrey Grodzovsky 				dc->res_pool,
24641dc90497SAndrey Grodzovsky 			del_pipe->stream_res.stream_enc,
24651dc90497SAndrey Grodzovsky 			false);
2466d3dfceb5SAurabindo Pillai 
246798ce7d32SWenjing Liu 	if (dc->link_srv->dp_is_128b_132b_signal(del_pipe)) {
2468f01ee019SFangzhi Zuo 		update_hpo_dp_stream_engine_usage(
2469f01ee019SFangzhi Zuo 			&new_ctx->res_ctx, dc->res_pool,
2470f01ee019SFangzhi Zuo 			del_pipe->stream_res.hpo_dp_stream_enc,
2471f01ee019SFangzhi Zuo 			false);
24726dd8931bSWenjing Liu 		remove_hpo_dp_link_enc_from_ctx(&new_ctx->res_ctx, del_pipe, del_pipe->stream);
2473f01ee019SFangzhi Zuo 	}
2474f01ee019SFangzhi Zuo 
24751dc90497SAndrey Grodzovsky 	if (del_pipe->stream_res.audio)
24761dc90497SAndrey Grodzovsky 		update_audio_usage(
24771dc90497SAndrey Grodzovsky 			&new_ctx->res_ctx,
24781dc90497SAndrey Grodzovsky 			dc->res_pool,
24791dc90497SAndrey Grodzovsky 			del_pipe->stream_res.audio,
24801dc90497SAndrey Grodzovsky 			false);
24811dc90497SAndrey Grodzovsky 
24829d0dcecdSHarry Wentland 	resource_unreference_clock_source(&new_ctx->res_ctx,
24839d0dcecdSHarry Wentland 					  dc->res_pool,
24849d0dcecdSHarry Wentland 					  del_pipe->clock_source);
24859d0dcecdSHarry Wentland 
2486e56ae556SNikola Cornij 	if (dc->res_pool->funcs->remove_stream_from_ctx)
2487e56ae556SNikola Cornij 		dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
2488e56ae556SNikola Cornij 
248922498036SDmytro Laktyushkin 	while (odm_pipe) {
249022498036SDmytro Laktyushkin 		struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
249122498036SDmytro Laktyushkin 
249222498036SDmytro Laktyushkin 		memset(odm_pipe, 0, sizeof(*odm_pipe));
249322498036SDmytro Laktyushkin 		odm_pipe = next_odm_pipe;
249422498036SDmytro Laktyushkin 	}
24951dc90497SAndrey Grodzovsky 	memset(del_pipe, 0, sizeof(*del_pipe));
24966ffaa6fcSDmytro Laktyushkin 
24971dc90497SAndrey Grodzovsky 	for (i = 0; i < new_ctx->stream_count; i++)
24981dc90497SAndrey Grodzovsky 		if (new_ctx->streams[i] == stream)
24991dc90497SAndrey Grodzovsky 			break;
25001dc90497SAndrey Grodzovsky 
25011dc90497SAndrey Grodzovsky 	if (new_ctx->streams[i] != stream) {
25021dc90497SAndrey Grodzovsky 		DC_ERROR("Context doesn't have stream %p !\n", stream);
25031dc90497SAndrey Grodzovsky 		return DC_ERROR_UNEXPECTED;
25041dc90497SAndrey Grodzovsky 	}
25051dc90497SAndrey Grodzovsky 
25061dc90497SAndrey Grodzovsky 	dc_stream_release(new_ctx->streams[i]);
25071dc90497SAndrey Grodzovsky 	new_ctx->stream_count--;
25081dc90497SAndrey Grodzovsky 
25091dc90497SAndrey Grodzovsky 	/* Trim back arrays */
25101dc90497SAndrey Grodzovsky 	for (; i < new_ctx->stream_count; i++) {
25111dc90497SAndrey Grodzovsky 		new_ctx->streams[i] = new_ctx->streams[i + 1];
25121dc90497SAndrey Grodzovsky 		new_ctx->stream_status[i] = new_ctx->stream_status[i + 1];
25131dc90497SAndrey Grodzovsky 	}
25141dc90497SAndrey Grodzovsky 
25151dc90497SAndrey Grodzovsky 	new_ctx->streams[new_ctx->stream_count] = NULL;
25161dc90497SAndrey Grodzovsky 	memset(
25171dc90497SAndrey Grodzovsky 			&new_ctx->stream_status[new_ctx->stream_count],
25181dc90497SAndrey Grodzovsky 			0,
25191dc90497SAndrey Grodzovsky 			sizeof(new_ctx->stream_status[0]));
25201dc90497SAndrey Grodzovsky 
25211dc90497SAndrey Grodzovsky 	return DC_OK;
25221dc90497SAndrey Grodzovsky }
25231dc90497SAndrey Grodzovsky 
find_pll_sharable_stream(struct dc_stream_state * stream_needs_pll,struct dc_state * context)25240971c40eSHarry Wentland static struct dc_stream_state *find_pll_sharable_stream(
25250971c40eSHarry Wentland 		struct dc_stream_state *stream_needs_pll,
2526608ac7bbSJerry Zuo 		struct dc_state *context)
25274562236bSHarry Wentland {
2528ab2541b6SAric Cyr 	int i;
25294562236bSHarry Wentland 
2530ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
25310971c40eSHarry Wentland 		struct dc_stream_state *stream_has_pll = context->streams[i];
25324562236bSHarry Wentland 
25334562236bSHarry Wentland 		/* We are looking for non dp, non virtual stream */
25344562236bSHarry Wentland 		if (resource_are_streams_timing_synchronizable(
25354562236bSHarry Wentland 			stream_needs_pll, stream_has_pll)
25364562236bSHarry Wentland 			&& !dc_is_dp_signal(stream_has_pll->signal)
2537ceb3dbb4SJun Lei 			&& stream_has_pll->link->connector_signal
25384562236bSHarry Wentland 			!= SIGNAL_TYPE_VIRTUAL)
25394562236bSHarry Wentland 			return stream_has_pll;
2540ab2541b6SAric Cyr 
25414562236bSHarry Wentland 	}
25424562236bSHarry Wentland 
25434562236bSHarry Wentland 	return NULL;
25444562236bSHarry Wentland }
25454562236bSHarry Wentland 
get_norm_pix_clk(const struct dc_crtc_timing * timing)25464562236bSHarry Wentland static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
25474562236bSHarry Wentland {
2548380604e2SKen Chalmers 	uint32_t pix_clk = timing->pix_clk_100hz;
25494562236bSHarry Wentland 	uint32_t normalized_pix_clk = pix_clk;
25504562236bSHarry Wentland 
25514562236bSHarry Wentland 	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
25524562236bSHarry Wentland 		pix_clk /= 2;
2553cc4d99b8SCharlene Liu 	if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
25544562236bSHarry Wentland 		switch (timing->display_color_depth) {
25558897810aSJulian Parkin 		case COLOR_DEPTH_666:
25564562236bSHarry Wentland 		case COLOR_DEPTH_888:
25574562236bSHarry Wentland 			normalized_pix_clk = pix_clk;
25584562236bSHarry Wentland 			break;
25594562236bSHarry Wentland 		case COLOR_DEPTH_101010:
25604562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 30) / 24;
25614562236bSHarry Wentland 			break;
25624562236bSHarry Wentland 		case COLOR_DEPTH_121212:
25634562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 36) / 24;
25644562236bSHarry Wentland 		break;
25654562236bSHarry Wentland 		case COLOR_DEPTH_161616:
25664562236bSHarry Wentland 			normalized_pix_clk = (pix_clk * 48) / 24;
25674562236bSHarry Wentland 		break;
25684562236bSHarry Wentland 		default:
25694562236bSHarry Wentland 			ASSERT(0);
25704562236bSHarry Wentland 		break;
25714562236bSHarry Wentland 		}
2572cc4d99b8SCharlene Liu 	}
25734562236bSHarry Wentland 	return normalized_pix_clk;
25744562236bSHarry Wentland }
25754562236bSHarry Wentland 
calculate_phy_pix_clks(struct dc_stream_state * stream)25760971c40eSHarry Wentland static void calculate_phy_pix_clks(struct dc_stream_state *stream)
25774562236bSHarry Wentland {
25784562236bSHarry Wentland 	/* update actual pixel clock on all streams */
25794562236bSHarry Wentland 	if (dc_is_hdmi_signal(stream->signal))
25804562236bSHarry Wentland 		stream->phy_pix_clk = get_norm_pix_clk(
2581380604e2SKen Chalmers 			&stream->timing) / 10;
25824562236bSHarry Wentland 	else
25834562236bSHarry Wentland 		stream->phy_pix_clk =
2584380604e2SKen Chalmers 			stream->timing.pix_clk_100hz / 10;
258539c03e00SCharlene Liu 
258639c03e00SCharlene Liu 	if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
258739c03e00SCharlene Liu 		stream->phy_pix_clk *= 2;
25884562236bSHarry Wentland }
25894562236bSHarry Wentland 
acquire_resource_from_hw_enabled_state(struct resource_context * res_ctx,const struct resource_pool * pool,struct dc_stream_state * stream)2590d2d7885fSAnthony Koo static int acquire_resource_from_hw_enabled_state(
2591d2d7885fSAnthony Koo 		struct resource_context *res_ctx,
2592d2d7885fSAnthony Koo 		const struct resource_pool *pool,
2593d2d7885fSAnthony Koo 		struct dc_stream_state *stream)
2594d2d7885fSAnthony Koo {
2595d2d7885fSAnthony Koo 	struct dc_link *link = stream->link;
259608b66279SMartin Leung 	unsigned int i, inst, tg_inst = 0;
2597663d2daeSDuncan Ma 	uint32_t numPipes = 1;
2598663d2daeSDuncan Ma 	uint32_t id_src[4] = {0};
2599d2d7885fSAnthony Koo 
2600d2d7885fSAnthony Koo 	/* Check for enabled DIG to identify enabled display */
2601d2d7885fSAnthony Koo 	if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
2602d2d7885fSAnthony Koo 		return -1;
2603d2d7885fSAnthony Koo 
26045ec43edaSMartin Leung 	inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
2605d2d7885fSAnthony Koo 
26067f7652eeSMartin Leung 	if (inst == ENGINE_ID_UNKNOWN)
260775441d9dSMikita Lipski 		return -1;
2608d2d7885fSAnthony Koo 
26097f7652eeSMartin Leung 	for (i = 0; i < pool->stream_enc_count; i++) {
26107f7652eeSMartin Leung 		if (pool->stream_enc[i]->id == inst) {
26117f7652eeSMartin Leung 			tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
26127f7652eeSMartin Leung 				pool->stream_enc[i]);
26137f7652eeSMartin Leung 			break;
26147f7652eeSMartin Leung 		}
26157f7652eeSMartin Leung 	}
2616d2d7885fSAnthony Koo 
26177f7652eeSMartin Leung 	// tg_inst not found
26187f7652eeSMartin Leung 	if (i == pool->stream_enc_count)
261975441d9dSMikita Lipski 		return -1;
26205ec43edaSMartin Leung 
26215ec43edaSMartin Leung 	if (tg_inst >= pool->timing_generator_count)
262275441d9dSMikita Lipski 		return -1;
26235ec43edaSMartin Leung 
26245ec43edaSMartin Leung 	if (!res_ctx->pipe_ctx[tg_inst].stream) {
26255ec43edaSMartin Leung 		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst];
26265ec43edaSMartin Leung 
26276d5276cdSSung Joon Kim 		pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
2628663d2daeSDuncan Ma 		id_src[0] = tg_inst;
2629663d2daeSDuncan Ma 
2630663d2daeSDuncan Ma 		if (pipe_ctx->stream_res.tg->funcs->get_optc_source)
2631663d2daeSDuncan Ma 			pipe_ctx->stream_res.tg->funcs->get_optc_source(pipe_ctx->stream_res.tg,
2632663d2daeSDuncan Ma 						&numPipes, &id_src[0], &id_src[1]);
2633663d2daeSDuncan Ma 
26346d5276cdSSung Joon Kim 		if (id_src[0] == 0xf && id_src[1] == 0xf) {
26356d5276cdSSung Joon Kim 			id_src[0] = tg_inst;
26366d5276cdSSung Joon Kim 			numPipes = 1;
26376d5276cdSSung Joon Kim 		}
26386d5276cdSSung Joon Kim 
2639663d2daeSDuncan Ma 		for (i = 0; i < numPipes; i++) {
2640663d2daeSDuncan Ma 			//Check if src id invalid
2641663d2daeSDuncan Ma 			if (id_src[i] == 0xf)
2642663d2daeSDuncan Ma 				return -1;
2643663d2daeSDuncan Ma 
26443e80a5b0SDuncan Ma 			pipe_ctx = &res_ctx->pipe_ctx[id_src[i]];
26453e80a5b0SDuncan Ma 
26465ec43edaSMartin Leung 			pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
2647663d2daeSDuncan Ma 			pipe_ctx->plane_res.mi = pool->mis[id_src[i]];
2648663d2daeSDuncan Ma 			pipe_ctx->plane_res.hubp = pool->hubps[id_src[i]];
2649663d2daeSDuncan Ma 			pipe_ctx->plane_res.ipp = pool->ipps[id_src[i]];
2650663d2daeSDuncan Ma 			pipe_ctx->plane_res.xfm = pool->transforms[id_src[i]];
2651663d2daeSDuncan Ma 			pipe_ctx->plane_res.dpp = pool->dpps[id_src[i]];
2652663d2daeSDuncan Ma 			pipe_ctx->stream_res.opp = pool->opps[id_src[i]];
26535ec43edaSMartin Leung 
2654663d2daeSDuncan Ma 			if (pool->dpps[id_src[i]]) {
2655663d2daeSDuncan Ma 				pipe_ctx->plane_res.mpcc_inst = pool->dpps[id_src[i]]->inst;
2656ccce745cSMartin Leung 
2657ccce745cSMartin Leung 				if (pool->mpc->funcs->read_mpcc_state) {
2658ccce745cSMartin Leung 					struct mpcc_state s = {0};
26593e80a5b0SDuncan Ma 
2660ccce745cSMartin Leung 					pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s);
26613e80a5b0SDuncan Ma 
2662ccce745cSMartin Leung 					if (s.dpp_id < MAX_MPCC)
2663663d2daeSDuncan Ma 						pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id =
2664663d2daeSDuncan Ma 								s.dpp_id;
26653e80a5b0SDuncan Ma 
2666ccce745cSMartin Leung 					if (s.bot_mpcc_id < MAX_MPCC)
2667ccce745cSMartin Leung 						pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot =
2668ccce745cSMartin Leung 								&pool->mpc->mpcc_array[s.bot_mpcc_id];
26693e80a5b0SDuncan Ma 
2670ccce745cSMartin Leung 					if (s.opp_id < MAX_OPP)
2671ccce745cSMartin Leung 						pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id;
2672ccce745cSMartin Leung 				}
2673ccce745cSMartin Leung 			}
2674663d2daeSDuncan Ma 			pipe_ctx->pipe_idx = id_src[i];
2675663d2daeSDuncan Ma 
2676663d2daeSDuncan Ma 			if (id_src[i] >= pool->timing_generator_count) {
2677663d2daeSDuncan Ma 				id_src[i] = pool->timing_generator_count - 1;
26783e80a5b0SDuncan Ma 
2679663d2daeSDuncan Ma 				pipe_ctx->stream_res.tg = pool->timing_generators[id_src[i]];
2680663d2daeSDuncan Ma 				pipe_ctx->stream_res.opp = pool->opps[id_src[i]];
2681663d2daeSDuncan Ma 			}
2682d2d7885fSAnthony Koo 
2683d2d7885fSAnthony Koo 			pipe_ctx->stream = stream;
2684663d2daeSDuncan Ma 		}
2685663d2daeSDuncan Ma 
2686663d2daeSDuncan Ma 		if (numPipes == 2) {
2687663d2daeSDuncan Ma 			stream->apply_boot_odm_mode = dm_odm_combine_policy_2to1;
2688663d2daeSDuncan Ma 			res_ctx->pipe_ctx[id_src[0]].next_odm_pipe = &res_ctx->pipe_ctx[id_src[1]];
2689663d2daeSDuncan Ma 			res_ctx->pipe_ctx[id_src[0]].prev_odm_pipe = NULL;
2690663d2daeSDuncan Ma 			res_ctx->pipe_ctx[id_src[1]].next_odm_pipe = NULL;
2691663d2daeSDuncan Ma 			res_ctx->pipe_ctx[id_src[1]].prev_odm_pipe = &res_ctx->pipe_ctx[id_src[0]];
2692663d2daeSDuncan Ma 		} else
2693663d2daeSDuncan Ma 			stream->apply_boot_odm_mode = dm_odm_combine_mode_disabled;
2694663d2daeSDuncan Ma 
2695663d2daeSDuncan Ma 		return id_src[0];
2696d2d7885fSAnthony Koo 	}
2697d2d7885fSAnthony Koo 
2698d2d7885fSAnthony Koo 	return -1;
2699d2d7885fSAnthony Koo }
2700d2d7885fSAnthony Koo 
mark_seamless_boot_stream(const struct dc * dc,struct dc_stream_state * stream)270196b5e3e1SRaymond Yang static void mark_seamless_boot_stream(
270296b5e3e1SRaymond Yang 		const struct dc  *dc,
270396b5e3e1SRaymond Yang 		struct dc_stream_state *stream)
270496b5e3e1SRaymond Yang {
270596b5e3e1SRaymond Yang 	struct dc_bios *dcb = dc->ctx->dc_bios;
270696b5e3e1SRaymond Yang 
270796b5e3e1SRaymond Yang 	if (dc->config.allow_seamless_boot_optimization &&
270896b5e3e1SRaymond Yang 			!dcb->funcs->is_accelerated_mode(dcb)) {
270998ea24e6SPaul Hsieh 		if (dc_validate_boot_timing(dc, stream->sink, &stream->timing))
271096b5e3e1SRaymond Yang 			stream->apply_seamless_boot_optimization = true;
271196b5e3e1SRaymond Yang 	}
271296b5e3e1SRaymond Yang }
271396b5e3e1SRaymond Yang 
resource_map_pool_resources(const struct dc * dc,struct dc_state * context,struct dc_stream_state * stream)27144562236bSHarry Wentland enum dc_status resource_map_pool_resources(
2715fb3466a4SBhawanpreet Lakha 		const struct dc  *dc,
2716608ac7bbSJerry Zuo 		struct dc_state *context,
27171dc90497SAndrey Grodzovsky 		struct dc_stream_state *stream)
27184562236bSHarry Wentland {
2719a2b8659dSTony Cheng 	const struct resource_pool *pool = dc->res_pool;
27201dc90497SAndrey Grodzovsky 	int i;
27211dc90497SAndrey Grodzovsky 	struct dc_context *dc_ctx = dc->ctx;
27221dc90497SAndrey Grodzovsky 	struct pipe_ctx *pipe_ctx = NULL;
27231dc90497SAndrey Grodzovsky 	int pipe_idx = -1;
27244562236bSHarry Wentland 
272508e1c28dSYogesh Mohan Marimuthu 	calculate_phy_pix_clks(stream);
272608e1c28dSYogesh Mohan Marimuthu 
272796b5e3e1SRaymond Yang 	mark_seamless_boot_stream(dc, stream);
272846570f09SAnthony Koo 
272996b5e3e1SRaymond Yang 	if (stream->apply_seamless_boot_optimization) {
2730d2d7885fSAnthony Koo 		pipe_idx = acquire_resource_from_hw_enabled_state(
2731d2d7885fSAnthony Koo 				&context->res_ctx,
2732d2d7885fSAnthony Koo 				pool,
2733d2d7885fSAnthony Koo 				stream);
273496b5e3e1SRaymond Yang 		if (pipe_idx < 0)
273596b5e3e1SRaymond Yang 			/* hw resource was assigned to other stream */
273696b5e3e1SRaymond Yang 			stream->apply_seamless_boot_optimization = false;
273796b5e3e1SRaymond Yang 	}
2738d2d7885fSAnthony Koo 
2739d2d7885fSAnthony Koo 	if (pipe_idx < 0)
27404562236bSHarry Wentland 		/* acquire new resources */
27415d11e9fcSDmytro Laktyushkin 		pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
27421dc90497SAndrey Grodzovsky 
27435d11e9fcSDmytro Laktyushkin 	if (pipe_idx < 0)
274413ab1b44SYongqiang Sun 		pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
274513ab1b44SYongqiang Sun 
2746c5b38aecSDmytro Laktyushkin 	if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL)
27474562236bSHarry Wentland 		return DC_NO_CONTROLLER_RESOURCE;
27484562236bSHarry Wentland 
27494562236bSHarry Wentland 	pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
27504562236bSHarry Wentland 
27518e9c4c8cSHarry Wentland 	pipe_ctx->stream_res.stream_enc =
275278cc70b1SWesley Chalmers 		dc->res_pool->funcs->find_first_free_match_stream_enc_for_link(
2753a2b8659dSTony Cheng 			&context->res_ctx, pool, stream);
27544562236bSHarry Wentland 
27558e9c4c8cSHarry Wentland 	if (!pipe_ctx->stream_res.stream_enc)
275638684e46SEric Bernstein 		return DC_NO_STREAM_ENC_RESOURCE;
27574562236bSHarry Wentland 
27581dc90497SAndrey Grodzovsky 	update_stream_engine_usage(
2759a2b8659dSTony Cheng 		&context->res_ctx, pool,
27601dc90497SAndrey Grodzovsky 		pipe_ctx->stream_res.stream_enc,
27611dc90497SAndrey Grodzovsky 		true);
27624562236bSHarry Wentland 
2763f01ee019SFangzhi Zuo 	/* Allocate DP HPO Stream Encoder based on signal, hw capabilities
2764f01ee019SFangzhi Zuo 	 * and link settings
2765f01ee019SFangzhi Zuo 	 */
2766017860c9SWenjing Liu 	if (dc_is_dp_signal(stream->signal)) {
276798ce7d32SWenjing Liu 		if (!dc->link_srv->dp_decide_link_settings(stream, &pipe_ctx->link_config.dp_link_settings))
2768017860c9SWenjing Liu 			return DC_FAIL_DP_LINK_BANDWIDTH;
276998ce7d32SWenjing Liu 		if (dc->link_srv->dp_get_encoding_format(
277098ce7d32SWenjing Liu 				&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) {
2771f01ee019SFangzhi Zuo 			pipe_ctx->stream_res.hpo_dp_stream_enc =
2772f01ee019SFangzhi Zuo 					find_first_free_match_hpo_dp_stream_enc_for_link(
2773f01ee019SFangzhi Zuo 							&context->res_ctx, pool, stream);
2774f01ee019SFangzhi Zuo 
2775f01ee019SFangzhi Zuo 			if (!pipe_ctx->stream_res.hpo_dp_stream_enc)
2776f01ee019SFangzhi Zuo 				return DC_NO_STREAM_ENC_RESOURCE;
2777f01ee019SFangzhi Zuo 
2778f01ee019SFangzhi Zuo 			update_hpo_dp_stream_engine_usage(
2779f01ee019SFangzhi Zuo 					&context->res_ctx, pool,
2780f01ee019SFangzhi Zuo 					pipe_ctx->stream_res.hpo_dp_stream_enc,
2781f01ee019SFangzhi Zuo 					true);
27826dd8931bSWenjing Liu 			if (!add_hpo_dp_link_enc_to_ctx(&context->res_ctx, pool, pipe_ctx, stream))
27836dd8931bSWenjing Liu 				return DC_NO_LINK_ENC_RESOURCE;
2784f01ee019SFangzhi Zuo 		}
2785f01ee019SFangzhi Zuo 	}
2786f01ee019SFangzhi Zuo 
27874562236bSHarry Wentland 	/* TODO: Add check if ASIC support and EDID audio */
2788ceb3dbb4SJun Lei 	if (!stream->converter_disable_audio &&
27894562236bSHarry Wentland 	    dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
2790ce08aad3SAlvin Lee 	    stream->audio_info.mode_count && stream->audio_info.flags.all) {
2791afaacef4SHarry Wentland 		pipe_ctx->stream_res.audio = find_first_free_audio(
2792f24b0522SPaul Hsieh 		&context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version);
27934562236bSHarry Wentland 
27944562236bSHarry Wentland 		/*
27954562236bSHarry Wentland 		 * Audio assigned in order first come first get.
27964562236bSHarry Wentland 		 * There are asics which has number of audio
27974562236bSHarry Wentland 		 * resources less then number of pipes
27984562236bSHarry Wentland 		 */
2799afaacef4SHarry Wentland 		if (pipe_ctx->stream_res.audio)
28001dc90497SAndrey Grodzovsky 			update_audio_usage(&context->res_ctx, pool,
28011dc90497SAndrey Grodzovsky 					   pipe_ctx->stream_res.audio, true);
28024562236bSHarry Wentland 	}
28034562236bSHarry Wentland 
28049aef1a31SSivapiriyanKumarasamy 	/* Add ABM to the resource if on EDP */
28055dba4991SBhawanpreet Lakha 	if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) {
28065dba4991SBhawanpreet Lakha 		if (pool->abm)
28079aef1a31SSivapiriyanKumarasamy 			pipe_ctx->stream_res.abm = pool->abm;
28085dba4991SBhawanpreet Lakha 		else
28095dba4991SBhawanpreet Lakha 			pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst];
28105dba4991SBhawanpreet Lakha 	}
28119aef1a31SSivapiriyanKumarasamy 
28121dc90497SAndrey Grodzovsky 	for (i = 0; i < context->stream_count; i++)
28131dc90497SAndrey Grodzovsky 		if (context->streams[i] == stream) {
28146b670fa9SHarry Wentland 			context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
28153f0940f8SCharlene Liu 			context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst;
28165fdb7c4cSNicholas Kazlauskas 			context->stream_status[i].audio_inst =
28175fdb7c4cSNicholas Kazlauskas 				pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1;
28185fdb7c4cSNicholas Kazlauskas 
28191dc90497SAndrey Grodzovsky 			return DC_OK;
28204562236bSHarry Wentland 		}
28214562236bSHarry Wentland 
28221dc90497SAndrey Grodzovsky 	DC_ERROR("Stream %p not found in new ctx!\n", stream);
28231dc90497SAndrey Grodzovsky 	return DC_ERROR_UNEXPECTED;
28244562236bSHarry Wentland }
28254562236bSHarry Wentland 
28262119aa17SDavid Francis /**
28272119aa17SDavid Francis  * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state
2828fa0fc4fbSRodrigo Siqueira  *
28292119aa17SDavid Francis  * @dc: copy out of dc->current_state
28302119aa17SDavid Francis  * @dst_ctx: copy into this
2831fa0fc4fbSRodrigo Siqueira  *
2832fa0fc4fbSRodrigo Siqueira  * This function makes a shallow copy of the current DC state and increments
2833fa0fc4fbSRodrigo Siqueira  * refcounts on existing streams and planes.
28342119aa17SDavid Francis  */
dc_resource_state_copy_construct_current(const struct dc * dc,struct dc_state * dst_ctx)2835f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct_current(
28361dc90497SAndrey Grodzovsky 		const struct dc *dc,
2837608ac7bbSJerry Zuo 		struct dc_state *dst_ctx)
28381dc90497SAndrey Grodzovsky {
2839f36cc577SBhawanpreet Lakha 	dc_resource_state_copy_construct(dc->current_state, dst_ctx);
28401dc90497SAndrey Grodzovsky }
28411dc90497SAndrey Grodzovsky 
2842ab8db3e1SAndrey Grodzovsky 
dc_resource_state_construct(const struct dc * dc,struct dc_state * dst_ctx)2843ab8db3e1SAndrey Grodzovsky void dc_resource_state_construct(
2844ab8db3e1SAndrey Grodzovsky 		const struct dc *dc,
2845ab8db3e1SAndrey Grodzovsky 		struct dc_state *dst_ctx)
2846ab8db3e1SAndrey Grodzovsky {
2847dc88b4a6SEric Yang 	dst_ctx->clk_mgr = dc->clk_mgr;
28487a47c882SJimmy Kizito 
28497a47c882SJimmy Kizito 	/* Initialise DIG link encoder resource tracking variables. */
28507a47c882SJimmy Kizito 	link_enc_cfg_init(dc, dst_ctx);
2851ab8db3e1SAndrey Grodzovsky }
2852ab8db3e1SAndrey Grodzovsky 
28536d822156SNikola Cornij 
dc_resource_is_dsc_encoding_supported(const struct dc * dc)28546d822156SNikola Cornij bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
28556d822156SNikola Cornij {
285684ce38c7SChris Park 	if (dc->res_pool == NULL)
285784ce38c7SChris Park 		return false;
285884ce38c7SChris Park 
28596d822156SNikola Cornij 	return dc->res_pool->res_cap->num_dsc > 0;
28606d822156SNikola Cornij }
28616d822156SNikola Cornij 
planes_changed_for_existing_stream(struct dc_state * context,struct dc_stream_state * stream,const struct dc_validation_set set[],int set_count)2862a5e39ae2SRodrigo Siqueira static bool planes_changed_for_existing_stream(struct dc_state *context,
2863a5e39ae2SRodrigo Siqueira 					       struct dc_stream_state *stream,
2864a5e39ae2SRodrigo Siqueira 					       const struct dc_validation_set set[],
2865a5e39ae2SRodrigo Siqueira 					       int set_count)
2866a5e39ae2SRodrigo Siqueira {
2867a5e39ae2SRodrigo Siqueira 	int i, j;
2868a5e39ae2SRodrigo Siqueira 	struct dc_stream_status *stream_status = NULL;
2869a5e39ae2SRodrigo Siqueira 
2870a5e39ae2SRodrigo Siqueira 	for (i = 0; i < context->stream_count; i++) {
2871a5e39ae2SRodrigo Siqueira 		if (context->streams[i] == stream) {
2872a5e39ae2SRodrigo Siqueira 			stream_status = &context->stream_status[i];
2873a5e39ae2SRodrigo Siqueira 			break;
2874a5e39ae2SRodrigo Siqueira 		}
2875a5e39ae2SRodrigo Siqueira 	}
2876a5e39ae2SRodrigo Siqueira 
2877a5e39ae2SRodrigo Siqueira 	if (!stream_status)
2878a5e39ae2SRodrigo Siqueira 		ASSERT(0);
2879a5e39ae2SRodrigo Siqueira 
2880a5e39ae2SRodrigo Siqueira 	for (i = 0; i < set_count; i++)
2881a5e39ae2SRodrigo Siqueira 		if (set[i].stream == stream)
2882a5e39ae2SRodrigo Siqueira 			break;
2883a5e39ae2SRodrigo Siqueira 
2884a5e39ae2SRodrigo Siqueira 	if (i == set_count)
2885a5e39ae2SRodrigo Siqueira 		ASSERT(0);
2886a5e39ae2SRodrigo Siqueira 
2887a5e39ae2SRodrigo Siqueira 	if (set[i].plane_count != stream_status->plane_count)
2888a5e39ae2SRodrigo Siqueira 		return true;
2889a5e39ae2SRodrigo Siqueira 
2890a5e39ae2SRodrigo Siqueira 	for (j = 0; j < set[i].plane_count; j++)
2891a5e39ae2SRodrigo Siqueira 		if (set[i].plane_states[j] != stream_status->plane_states[j])
2892a5e39ae2SRodrigo Siqueira 			return true;
2893a5e39ae2SRodrigo Siqueira 
2894a5e39ae2SRodrigo Siqueira 	return false;
2895a5e39ae2SRodrigo Siqueira }
28966d822156SNikola Cornij 
28972119aa17SDavid Francis /**
2898a5e39ae2SRodrigo Siqueira  * dc_validate_with_context - Validate and update the potential new stream in the context object
2899a5e39ae2SRodrigo Siqueira  *
2900a5e39ae2SRodrigo Siqueira  * @dc: Used to get the current state status
2901a5e39ae2SRodrigo Siqueira  * @set: An array of dc_validation_set with all the current streams reference
2902a5e39ae2SRodrigo Siqueira  * @set_count: Total of streams
2903a5e39ae2SRodrigo Siqueira  * @context: New context
2904a5e39ae2SRodrigo Siqueira  * @fast_validate: Enable or disable fast validation
2905a5e39ae2SRodrigo Siqueira  *
2906a5e39ae2SRodrigo Siqueira  * This function updates the potential new stream in the context object. It
2907a5e39ae2SRodrigo Siqueira  * creates multiple lists for the add, remove, and unchanged streams. In
2908a5e39ae2SRodrigo Siqueira  * particular, if the unchanged streams have a plane that changed, it is
2909a5e39ae2SRodrigo Siqueira  * necessary to remove all planes from the unchanged streams. In summary, this
2910a5e39ae2SRodrigo Siqueira  * function is responsible for validating the new context.
2911a5e39ae2SRodrigo Siqueira  *
2912a5e39ae2SRodrigo Siqueira  * Return:
2913a5e39ae2SRodrigo Siqueira  * In case of success, return DC_OK (1), otherwise, return a DC error.
2914a5e39ae2SRodrigo Siqueira  */
dc_validate_with_context(struct dc * dc,const struct dc_validation_set set[],int set_count,struct dc_state * context,bool fast_validate)2915a5e39ae2SRodrigo Siqueira enum dc_status dc_validate_with_context(struct dc *dc,
2916a5e39ae2SRodrigo Siqueira 					const struct dc_validation_set set[],
2917a5e39ae2SRodrigo Siqueira 					int set_count,
2918a5e39ae2SRodrigo Siqueira 					struct dc_state *context,
2919a5e39ae2SRodrigo Siqueira 					bool fast_validate)
2920a5e39ae2SRodrigo Siqueira {
2921a5e39ae2SRodrigo Siqueira 	struct dc_stream_state *unchanged_streams[MAX_PIPES] = { 0 };
2922a5e39ae2SRodrigo Siqueira 	struct dc_stream_state *del_streams[MAX_PIPES] = { 0 };
2923a5e39ae2SRodrigo Siqueira 	struct dc_stream_state *add_streams[MAX_PIPES] = { 0 };
2924a5e39ae2SRodrigo Siqueira 	int old_stream_count = context->stream_count;
2925a5e39ae2SRodrigo Siqueira 	enum dc_status res = DC_ERROR_UNEXPECTED;
2926a5e39ae2SRodrigo Siqueira 	int unchanged_streams_count = 0;
2927a5e39ae2SRodrigo Siqueira 	int del_streams_count = 0;
2928a5e39ae2SRodrigo Siqueira 	int add_streams_count = 0;
2929a5e39ae2SRodrigo Siqueira 	bool found = false;
2930a5e39ae2SRodrigo Siqueira 	int i, j, k;
2931a5e39ae2SRodrigo Siqueira 
2932a5e39ae2SRodrigo Siqueira 	DC_LOGGER_INIT(dc->ctx->logger);
2933a5e39ae2SRodrigo Siqueira 
2934a5e39ae2SRodrigo Siqueira 	/* First build a list of streams to be remove from current context */
2935a5e39ae2SRodrigo Siqueira 	for (i = 0; i < old_stream_count; i++) {
2936a5e39ae2SRodrigo Siqueira 		struct dc_stream_state *stream = context->streams[i];
2937a5e39ae2SRodrigo Siqueira 
2938a5e39ae2SRodrigo Siqueira 		for (j = 0; j < set_count; j++) {
2939a5e39ae2SRodrigo Siqueira 			if (stream == set[j].stream) {
2940a5e39ae2SRodrigo Siqueira 				found = true;
2941a5e39ae2SRodrigo Siqueira 				break;
2942a5e39ae2SRodrigo Siqueira 			}
2943a5e39ae2SRodrigo Siqueira 		}
2944a5e39ae2SRodrigo Siqueira 
2945a5e39ae2SRodrigo Siqueira 		if (!found)
2946a5e39ae2SRodrigo Siqueira 			del_streams[del_streams_count++] = stream;
2947a5e39ae2SRodrigo Siqueira 
2948a5e39ae2SRodrigo Siqueira 		found = false;
2949a5e39ae2SRodrigo Siqueira 	}
2950a5e39ae2SRodrigo Siqueira 
2951a5e39ae2SRodrigo Siqueira 	/* Second, build a list of new streams */
2952a5e39ae2SRodrigo Siqueira 	for (i = 0; i < set_count; i++) {
2953a5e39ae2SRodrigo Siqueira 		struct dc_stream_state *stream = set[i].stream;
2954a5e39ae2SRodrigo Siqueira 
2955a5e39ae2SRodrigo Siqueira 		for (j = 0; j < old_stream_count; j++) {
2956a5e39ae2SRodrigo Siqueira 			if (stream == context->streams[j]) {
2957a5e39ae2SRodrigo Siqueira 				found = true;
2958a5e39ae2SRodrigo Siqueira 				break;
2959a5e39ae2SRodrigo Siqueira 			}
2960a5e39ae2SRodrigo Siqueira 		}
2961a5e39ae2SRodrigo Siqueira 
2962a5e39ae2SRodrigo Siqueira 		if (!found)
2963a5e39ae2SRodrigo Siqueira 			add_streams[add_streams_count++] = stream;
2964a5e39ae2SRodrigo Siqueira 
2965a5e39ae2SRodrigo Siqueira 		found = false;
2966a5e39ae2SRodrigo Siqueira 	}
2967a5e39ae2SRodrigo Siqueira 
2968a5e39ae2SRodrigo Siqueira 	/* Build a list of unchanged streams which is necessary for handling
2969a5e39ae2SRodrigo Siqueira 	 * planes change such as added, removed, and updated.
2970a5e39ae2SRodrigo Siqueira 	 */
2971a5e39ae2SRodrigo Siqueira 	for (i = 0; i < set_count; i++) {
2972a5e39ae2SRodrigo Siqueira 		/* Check if stream is part of the delete list */
2973a5e39ae2SRodrigo Siqueira 		for (j = 0; j < del_streams_count; j++) {
2974a5e39ae2SRodrigo Siqueira 			if (set[i].stream == del_streams[j]) {
2975a5e39ae2SRodrigo Siqueira 				found = true;
2976a5e39ae2SRodrigo Siqueira 				break;
2977a5e39ae2SRodrigo Siqueira 			}
2978a5e39ae2SRodrigo Siqueira 		}
2979a5e39ae2SRodrigo Siqueira 
2980a5e39ae2SRodrigo Siqueira 		if (!found) {
2981a5e39ae2SRodrigo Siqueira 			/* Check if stream is part of the add list */
2982a5e39ae2SRodrigo Siqueira 			for (j = 0; j < add_streams_count; j++) {
2983a5e39ae2SRodrigo Siqueira 				if (set[i].stream == add_streams[j]) {
2984a5e39ae2SRodrigo Siqueira 					found = true;
2985a5e39ae2SRodrigo Siqueira 					break;
2986a5e39ae2SRodrigo Siqueira 				}
2987a5e39ae2SRodrigo Siqueira 			}
2988a5e39ae2SRodrigo Siqueira 		}
2989a5e39ae2SRodrigo Siqueira 
2990a5e39ae2SRodrigo Siqueira 		if (!found)
2991a5e39ae2SRodrigo Siqueira 			unchanged_streams[unchanged_streams_count++] = set[i].stream;
2992a5e39ae2SRodrigo Siqueira 
2993a5e39ae2SRodrigo Siqueira 		found = false;
2994a5e39ae2SRodrigo Siqueira 	}
2995a5e39ae2SRodrigo Siqueira 
2996a5e39ae2SRodrigo Siqueira 	/* Remove all planes for unchanged streams if planes changed */
2997a5e39ae2SRodrigo Siqueira 	for (i = 0; i < unchanged_streams_count; i++) {
2998a5e39ae2SRodrigo Siqueira 		if (planes_changed_for_existing_stream(context,
2999a5e39ae2SRodrigo Siqueira 						       unchanged_streams[i],
3000a5e39ae2SRodrigo Siqueira 						       set,
3001a5e39ae2SRodrigo Siqueira 						       set_count)) {
3002a5e39ae2SRodrigo Siqueira 			if (!dc_rem_all_planes_for_stream(dc,
3003a5e39ae2SRodrigo Siqueira 							  unchanged_streams[i],
3004a5e39ae2SRodrigo Siqueira 							  context)) {
3005a5e39ae2SRodrigo Siqueira 				res = DC_FAIL_DETACH_SURFACES;
3006a5e39ae2SRodrigo Siqueira 				goto fail;
3007a5e39ae2SRodrigo Siqueira 			}
3008a5e39ae2SRodrigo Siqueira 		}
3009a5e39ae2SRodrigo Siqueira 	}
3010a5e39ae2SRodrigo Siqueira 
3011a5e39ae2SRodrigo Siqueira 	/* Remove all planes for removed streams and then remove the streams */
3012a5e39ae2SRodrigo Siqueira 	for (i = 0; i < del_streams_count; i++) {
3013a5e39ae2SRodrigo Siqueira 		/* Need to cpy the dwb data from the old stream in order to efc to work */
3014a5e39ae2SRodrigo Siqueira 		if (del_streams[i]->num_wb_info > 0) {
3015a5e39ae2SRodrigo Siqueira 			for (j = 0; j < add_streams_count; j++) {
3016a5e39ae2SRodrigo Siqueira 				if (del_streams[i]->sink == add_streams[j]->sink) {
3017a5e39ae2SRodrigo Siqueira 					add_streams[j]->num_wb_info = del_streams[i]->num_wb_info;
3018a5e39ae2SRodrigo Siqueira 					for (k = 0; k < del_streams[i]->num_wb_info; k++)
3019a5e39ae2SRodrigo Siqueira 						add_streams[j]->writeback_info[k] = del_streams[i]->writeback_info[k];
3020a5e39ae2SRodrigo Siqueira 				}
3021a5e39ae2SRodrigo Siqueira 			}
3022a5e39ae2SRodrigo Siqueira 		}
3023a5e39ae2SRodrigo Siqueira 
3024a5e39ae2SRodrigo Siqueira 		if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) {
3025a5e39ae2SRodrigo Siqueira 			res = DC_FAIL_DETACH_SURFACES;
3026a5e39ae2SRodrigo Siqueira 			goto fail;
3027a5e39ae2SRodrigo Siqueira 		}
3028a5e39ae2SRodrigo Siqueira 
3029a5e39ae2SRodrigo Siqueira 		res = dc_remove_stream_from_ctx(dc, context, del_streams[i]);
3030a5e39ae2SRodrigo Siqueira 		if (res != DC_OK)
3031a5e39ae2SRodrigo Siqueira 			goto fail;
3032a5e39ae2SRodrigo Siqueira 	}
3033a5e39ae2SRodrigo Siqueira 
3034170390e5SRodrigo Siqueira 	/* Swap seamless boot stream to pipe 0 (if needed) to ensure pipe_ctx
3035170390e5SRodrigo Siqueira 	 * matches. This may change in the future if seamless_boot_stream can be
3036170390e5SRodrigo Siqueira 	 * multiple.
3037170390e5SRodrigo Siqueira 	 */
3038170390e5SRodrigo Siqueira 	for (i = 0; i < add_streams_count; i++) {
3039170390e5SRodrigo Siqueira 		mark_seamless_boot_stream(dc, add_streams[i]);
3040170390e5SRodrigo Siqueira 		if (add_streams[i]->apply_seamless_boot_optimization && i != 0) {
3041170390e5SRodrigo Siqueira 			struct dc_stream_state *temp = add_streams[0];
3042170390e5SRodrigo Siqueira 
3043170390e5SRodrigo Siqueira 			add_streams[0] = add_streams[i];
3044170390e5SRodrigo Siqueira 			add_streams[i] = temp;
3045170390e5SRodrigo Siqueira 			break;
3046170390e5SRodrigo Siqueira 		}
3047170390e5SRodrigo Siqueira 	}
3048170390e5SRodrigo Siqueira 
3049a5e39ae2SRodrigo Siqueira 	/* Add new streams and then add all planes for the new stream */
3050a5e39ae2SRodrigo Siqueira 	for (i = 0; i < add_streams_count; i++) {
3051a5e39ae2SRodrigo Siqueira 		calculate_phy_pix_clks(add_streams[i]);
3052a5e39ae2SRodrigo Siqueira 		res = dc_add_stream_to_ctx(dc, context, add_streams[i]);
3053a5e39ae2SRodrigo Siqueira 		if (res != DC_OK)
3054a5e39ae2SRodrigo Siqueira 			goto fail;
3055a5e39ae2SRodrigo Siqueira 
3056a5e39ae2SRodrigo Siqueira 		if (!add_all_planes_for_stream(dc, add_streams[i], set, set_count, context)) {
3057a5e39ae2SRodrigo Siqueira 			res = DC_FAIL_ATTACH_SURFACES;
3058a5e39ae2SRodrigo Siqueira 			goto fail;
3059a5e39ae2SRodrigo Siqueira 		}
3060a5e39ae2SRodrigo Siqueira 	}
3061a5e39ae2SRodrigo Siqueira 
3062a5e39ae2SRodrigo Siqueira 	/* Add all planes for unchanged streams if planes changed */
3063a5e39ae2SRodrigo Siqueira 	for (i = 0; i < unchanged_streams_count; i++) {
3064a5e39ae2SRodrigo Siqueira 		if (planes_changed_for_existing_stream(context,
3065a5e39ae2SRodrigo Siqueira 						       unchanged_streams[i],
3066a5e39ae2SRodrigo Siqueira 						       set,
3067a5e39ae2SRodrigo Siqueira 						       set_count)) {
3068a5e39ae2SRodrigo Siqueira 			if (!add_all_planes_for_stream(dc, unchanged_streams[i], set, set_count, context)) {
3069a5e39ae2SRodrigo Siqueira 				res = DC_FAIL_ATTACH_SURFACES;
3070a5e39ae2SRodrigo Siqueira 				goto fail;
3071a5e39ae2SRodrigo Siqueira 			}
3072a5e39ae2SRodrigo Siqueira 		}
3073a5e39ae2SRodrigo Siqueira 	}
3074a5e39ae2SRodrigo Siqueira 
3075a5e39ae2SRodrigo Siqueira 	res = dc_validate_global_state(dc, context, fast_validate);
3076a5e39ae2SRodrigo Siqueira 
3077a5e39ae2SRodrigo Siqueira fail:
3078a5e39ae2SRodrigo Siqueira 	if (res != DC_OK)
3079a5e39ae2SRodrigo Siqueira 		DC_LOG_WARNING("%s:resource validation failed, dc_status:%d\n",
3080a5e39ae2SRodrigo Siqueira 			       __func__,
3081a5e39ae2SRodrigo Siqueira 			       res);
3082a5e39ae2SRodrigo Siqueira 
3083a5e39ae2SRodrigo Siqueira 	return res;
3084a5e39ae2SRodrigo Siqueira }
3085a5e39ae2SRodrigo Siqueira 
3086a5e39ae2SRodrigo Siqueira /**
3087a5e39ae2SRodrigo Siqueira  * dc_validate_global_state() - Determine if hardware can support a given state
3088a5e39ae2SRodrigo Siqueira  *
30892119aa17SDavid Francis  * @dc: dc struct for this driver
30902119aa17SDavid Francis  * @new_ctx: state to be validated
3091afcd526bSJoshua Aberback  * @fast_validate: set to true if only yes/no to support matters
30922119aa17SDavid Francis  *
3093a5e39ae2SRodrigo Siqueira  * Checks hardware resource availability and bandwidth requirement.
3094a5e39ae2SRodrigo Siqueira  *
3095a5e39ae2SRodrigo Siqueira  * Return:
3096a5e39ae2SRodrigo Siqueira  * DC_OK if the result can be programmed. Otherwise, an error code.
30972119aa17SDavid Francis  */
dc_validate_global_state(struct dc * dc,struct dc_state * new_ctx,bool fast_validate)3098e750d56dSYongqiang Sun enum dc_status dc_validate_global_state(
30991dc90497SAndrey Grodzovsky 		struct dc *dc,
3100afcd526bSJoshua Aberback 		struct dc_state *new_ctx,
3101afcd526bSJoshua Aberback 		bool fast_validate)
31021dc90497SAndrey Grodzovsky {
31031dc90497SAndrey Grodzovsky 	enum dc_status result = DC_ERROR_UNEXPECTED;
31041dc90497SAndrey Grodzovsky 	int i, j;
31051dc90497SAndrey Grodzovsky 
3106e41ab030SHarry Wentland 	if (!new_ctx)
3107e41ab030SHarry Wentland 		return DC_ERROR_UNEXPECTED;
3108e41ab030SHarry Wentland 
3109d596e5d0SYongqiang Sun 	if (dc->res_pool->funcs->validate_global) {
3110d596e5d0SYongqiang Sun 		result = dc->res_pool->funcs->validate_global(dc, new_ctx);
3111d596e5d0SYongqiang Sun 		if (result != DC_OK)
3112d596e5d0SYongqiang Sun 			return result;
3113d596e5d0SYongqiang Sun 	}
31141dc90497SAndrey Grodzovsky 
3115e41ab030SHarry Wentland 	for (i = 0; i < new_ctx->stream_count; i++) {
31161dc90497SAndrey Grodzovsky 		struct dc_stream_state *stream = new_ctx->streams[i];
31171dc90497SAndrey Grodzovsky 
31181dc90497SAndrey Grodzovsky 		for (j = 0; j < dc->res_pool->pipe_count; j++) {
31191dc90497SAndrey Grodzovsky 			struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j];
31201dc90497SAndrey Grodzovsky 
31211dc90497SAndrey Grodzovsky 			if (pipe_ctx->stream != stream)
31221dc90497SAndrey Grodzovsky 				continue;
31231dc90497SAndrey Grodzovsky 
31248d8c82b6SJoseph Gravenor 			if (dc->res_pool->funcs->patch_unknown_plane_state &&
312574eac5f3SSu Sung Chung 					pipe_ctx->plane_state &&
312674eac5f3SSu Sung Chung 					pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
31278d8c82b6SJoseph Gravenor 				result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state);
312874eac5f3SSu Sung Chung 				if (result != DC_OK)
312974eac5f3SSu Sung Chung 					return result;
313074eac5f3SSu Sung Chung 			}
313174eac5f3SSu Sung Chung 
31321dc90497SAndrey Grodzovsky 			/* Switch to dp clock source only if there is
31331dc90497SAndrey Grodzovsky 			 * no non dp stream that shares the same timing
31341dc90497SAndrey Grodzovsky 			 * with the dp stream.
31351dc90497SAndrey Grodzovsky 			 */
31361dc90497SAndrey Grodzovsky 			if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
31371dc90497SAndrey Grodzovsky 				!find_pll_sharable_stream(stream, new_ctx)) {
31381dc90497SAndrey Grodzovsky 
31399d0dcecdSHarry Wentland 				resource_unreference_clock_source(
31401dc90497SAndrey Grodzovsky 						&new_ctx->res_ctx,
31411dc90497SAndrey Grodzovsky 						dc->res_pool,
31429d0dcecdSHarry Wentland 						pipe_ctx->clock_source);
31434a629536SHarry Wentland 
31441dc90497SAndrey Grodzovsky 				pipe_ctx->clock_source = dc->res_pool->dp_clock_source;
31451dc90497SAndrey Grodzovsky 				resource_reference_clock_source(
31461dc90497SAndrey Grodzovsky 						&new_ctx->res_ctx,
31471dc90497SAndrey Grodzovsky 						dc->res_pool,
31481dc90497SAndrey Grodzovsky 						 pipe_ctx->clock_source);
31491dc90497SAndrey Grodzovsky 			}
31501dc90497SAndrey Grodzovsky 		}
31511dc90497SAndrey Grodzovsky 	}
31521dc90497SAndrey Grodzovsky 
31531dc90497SAndrey Grodzovsky 	result = resource_build_scaling_params_for_context(dc, new_ctx);
31541dc90497SAndrey Grodzovsky 
31551dc90497SAndrey Grodzovsky 	if (result == DC_OK)
3156afcd526bSJoshua Aberback 		if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate))
31571dc90497SAndrey Grodzovsky 			result = DC_FAIL_BANDWIDTH_VALIDATE;
31581dc90497SAndrey Grodzovsky 
3159ab644ea6SJimmy Kizito 	/*
3160ab644ea6SJimmy Kizito 	 * Only update link encoder to stream assignment after bandwidth validation passed.
3161ab644ea6SJimmy Kizito 	 * TODO: Split out assignment and validation.
3162ab644ea6SJimmy Kizito 	 */
3163ab644ea6SJimmy Kizito 	if (result == DC_OK && dc->res_pool->funcs->link_encs_assign && fast_validate == false)
3164ab644ea6SJimmy Kizito 		dc->res_pool->funcs->link_encs_assign(
3165ab644ea6SJimmy Kizito 			dc, new_ctx, new_ctx->streams, new_ctx->stream_count);
3166ab644ea6SJimmy Kizito 
31671dc90497SAndrey Grodzovsky 	return result;
31681dc90497SAndrey Grodzovsky }
31691dc90497SAndrey Grodzovsky 
patch_gamut_packet_checksum(struct dc_info_packet * gamut_packet)31706e4d6beeSTony Cheng static void patch_gamut_packet_checksum(
3171e09b6473SAnthony Koo 		struct dc_info_packet *gamut_packet)
31724562236bSHarry Wentland {
31734562236bSHarry Wentland 	/* For gamut we recalc checksum */
31746e4d6beeSTony Cheng 	if (gamut_packet->valid) {
31754562236bSHarry Wentland 		uint8_t chk_sum = 0;
31764562236bSHarry Wentland 		uint8_t *ptr;
31774562236bSHarry Wentland 		uint8_t i;
31784562236bSHarry Wentland 
31794562236bSHarry Wentland 		/*start of the Gamut data. */
31806e4d6beeSTony Cheng 		ptr = &gamut_packet->sb[3];
31814562236bSHarry Wentland 
31826e4d6beeSTony Cheng 		for (i = 0; i <= gamut_packet->sb[1]; i++)
31834562236bSHarry Wentland 			chk_sum += ptr[i];
31844562236bSHarry Wentland 
31856e4d6beeSTony Cheng 		gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
31861646a6feSAndrew Wong 	}
31874562236bSHarry Wentland }
31884562236bSHarry Wentland 
set_avi_info_frame(struct dc_info_packet * info_packet,struct pipe_ctx * pipe_ctx)31894562236bSHarry Wentland static void set_avi_info_frame(
3190e09b6473SAnthony Koo 		struct dc_info_packet *info_packet,
31914562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
31924562236bSHarry Wentland {
31930971c40eSHarry Wentland 	struct dc_stream_state *stream = pipe_ctx->stream;
31944562236bSHarry Wentland 	enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
31954562236bSHarry Wentland 	uint32_t pixel_encoding = 0;
31964562236bSHarry Wentland 	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
31974562236bSHarry Wentland 	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
31984562236bSHarry Wentland 	bool itc = false;
319950e27654SZeyu Fan 	uint8_t itc_value = 0;
32004562236bSHarry Wentland 	uint8_t cn0_cn1 = 0;
320150e27654SZeyu Fan 	unsigned int cn0_cn1_value = 0;
32024562236bSHarry Wentland 	uint8_t *check_sum = NULL;
32034562236bSHarry Wentland 	uint8_t byte_index = 0;
3204754e3673SAnthony Koo 	union hdmi_info_packet hdmi_info;
320550e27654SZeyu Fan 	union display_content_support support = {0};
32064fa086b9SLeo (Sunpeng) Li 	unsigned int vic = pipe_ctx->stream->timing.vic;
3207427a60c1SChris Park 	unsigned int rid = pipe_ctx->stream->timing.rid;
3208427a60c1SChris Park 	unsigned int fr_ind = pipe_ctx->stream->timing.fr_index;
320915e17335SCharlene Liu 	enum dc_timing_3d_format format;
32104562236bSHarry Wentland 
3211754e3673SAnthony Koo 	memset(&hdmi_info, 0, sizeof(union hdmi_info_packet));
3212754e3673SAnthony Koo 
32134fa086b9SLeo (Sunpeng) Li 	color_space = pipe_ctx->stream->output_color_space;
3214e5f2038eSCharlene Liu 	if (color_space == COLOR_SPACE_UNKNOWN)
32154fa086b9SLeo (Sunpeng) Li 		color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ?
3216e5f2038eSCharlene Liu 			COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709;
32174562236bSHarry Wentland 
32184562236bSHarry Wentland 	/* Initialize header */
3219e09b6473SAnthony Koo 	hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
32204562236bSHarry Wentland 	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
32214562236bSHarry Wentland 	* not be used in HDMI 2.0 (Section 10.1) */
3222e09b6473SAnthony Koo 	hdmi_info.bits.header.version = 2;
3223e09b6473SAnthony Koo 	hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE;
32244562236bSHarry Wentland 
32254562236bSHarry Wentland 	/*
32264562236bSHarry Wentland 	 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
32274562236bSHarry Wentland 	 * according to HDMI 2.0 spec (Section 10.1)
32284562236bSHarry Wentland 	 */
32294562236bSHarry Wentland 
32304fa086b9SLeo (Sunpeng) Li 	switch (stream->timing.pixel_encoding) {
32314562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR422:
32324562236bSHarry Wentland 		pixel_encoding = 1;
32334562236bSHarry Wentland 		break;
32344562236bSHarry Wentland 
32354562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR444:
32364562236bSHarry Wentland 		pixel_encoding = 2;
32374562236bSHarry Wentland 		break;
32384562236bSHarry Wentland 	case PIXEL_ENCODING_YCBCR420:
32394562236bSHarry Wentland 		pixel_encoding = 3;
32404562236bSHarry Wentland 		break;
32414562236bSHarry Wentland 
32424562236bSHarry Wentland 	case PIXEL_ENCODING_RGB:
32434562236bSHarry Wentland 	default:
32444562236bSHarry Wentland 		pixel_encoding = 0;
32454562236bSHarry Wentland 	}
32464562236bSHarry Wentland 
32474562236bSHarry Wentland 	/* Y0_Y1_Y2 : The pixel encoding */
32484562236bSHarry Wentland 	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
3249e09b6473SAnthony Koo 	hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding;
32504562236bSHarry Wentland 
32514562236bSHarry Wentland 	/* A0 = 1 Active Format Information valid */
3252e09b6473SAnthony Koo 	hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID;
32534562236bSHarry Wentland 
32544562236bSHarry Wentland 	/* B0, B1 = 3; Bar info data is valid */
3255e09b6473SAnthony Koo 	hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID;
32564562236bSHarry Wentland 
3257e09b6473SAnthony Koo 	hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM;
32584562236bSHarry Wentland 
32594562236bSHarry Wentland 	/* S0, S1 : Underscan / Overscan */
32604562236bSHarry Wentland 	/* TODO: un-hardcode scan type */
32614562236bSHarry Wentland 	scan_type = SCANNING_TYPE_UNDERSCAN;
3262e09b6473SAnthony Koo 	hdmi_info.bits.S0_S1 = scan_type;
32634562236bSHarry Wentland 
32644562236bSHarry Wentland 	/* C0, C1 : Colorimetry */
3265eaa7d830SJoshua Ashton 	switch (color_space) {
3266eaa7d830SJoshua Ashton 	case COLOR_SPACE_YCBCR709:
3267eaa7d830SJoshua Ashton 	case COLOR_SPACE_YCBCR709_LIMITED:
3268e09b6473SAnthony Koo 		hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
3269eaa7d830SJoshua Ashton 		break;
3270eaa7d830SJoshua Ashton 	case COLOR_SPACE_YCBCR601:
3271eaa7d830SJoshua Ashton 	case COLOR_SPACE_YCBCR601_LIMITED:
3272e09b6473SAnthony Koo 		hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601;
3273eaa7d830SJoshua Ashton 		break;
3274eaa7d830SJoshua Ashton 	case COLOR_SPACE_2020_RGB_FULLRANGE:
3275eaa7d830SJoshua Ashton 	case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
3276eaa7d830SJoshua Ashton 	case COLOR_SPACE_2020_YCBCR:
3277e09b6473SAnthony Koo 		hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
3278e09b6473SAnthony Koo 		hdmi_info.bits.C0_C1   = COLORIMETRY_EXTENDED;
3279eaa7d830SJoshua Ashton 		break;
3280eaa7d830SJoshua Ashton 	case COLOR_SPACE_ADOBERGB:
3281e09b6473SAnthony Koo 		hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
3282e09b6473SAnthony Koo 		hdmi_info.bits.C0_C1   = COLORIMETRY_EXTENDED;
3283eaa7d830SJoshua Ashton 		break;
3284eaa7d830SJoshua Ashton 	case COLOR_SPACE_SRGB:
3285eaa7d830SJoshua Ashton 	default:
3286eaa7d830SJoshua Ashton 		hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
3287eaa7d830SJoshua Ashton 		break;
3288534db198SAmy Zhang 	}
3289534db198SAmy Zhang 
3290b1a98cf8SMa Hanghong 	if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR &&
3291b1a98cf8SMa Hanghong 			stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
3292b1a98cf8SMa Hanghong 		hdmi_info.bits.EC0_EC2 = 0;
3293b1a98cf8SMa Hanghong 		hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
3294b1a98cf8SMa Hanghong 	}
3295b1a98cf8SMa Hanghong 
32964562236bSHarry Wentland 	/* TODO: un-hardcode aspect ratio */
32974fa086b9SLeo (Sunpeng) Li 	aspect = stream->timing.aspect_ratio;
32984562236bSHarry Wentland 
32994562236bSHarry Wentland 	switch (aspect) {
33004562236bSHarry Wentland 	case ASPECT_RATIO_4_3:
33014562236bSHarry Wentland 	case ASPECT_RATIO_16_9:
3302e09b6473SAnthony Koo 		hdmi_info.bits.M0_M1 = aspect;
33034562236bSHarry Wentland 		break;
33044562236bSHarry Wentland 
33054562236bSHarry Wentland 	case ASPECT_RATIO_NO_DATA:
33064562236bSHarry Wentland 	case ASPECT_RATIO_64_27:
33074562236bSHarry Wentland 	case ASPECT_RATIO_256_135:
33084562236bSHarry Wentland 	default:
3309e09b6473SAnthony Koo 		hdmi_info.bits.M0_M1 = 0;
33104562236bSHarry Wentland 	}
33114562236bSHarry Wentland 
33124562236bSHarry Wentland 	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
3313e09b6473SAnthony Koo 	hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
33144562236bSHarry Wentland 
33154562236bSHarry Wentland 	/* TODO: un-hardcode cn0_cn1 and itc */
331650e27654SZeyu Fan 
33174562236bSHarry Wentland 	cn0_cn1 = 0;
331850e27654SZeyu Fan 	cn0_cn1_value = 0;
331950e27654SZeyu Fan 
332050e27654SZeyu Fan 	itc = true;
332150e27654SZeyu Fan 	itc_value = 1;
332250e27654SZeyu Fan 
3323ceb3dbb4SJun Lei 	support = stream->content_support;
33244562236bSHarry Wentland 
33254562236bSHarry Wentland 	if (itc) {
332650e27654SZeyu Fan 		if (!support.bits.valid_content_type) {
332750e27654SZeyu Fan 			cn0_cn1_value = 0;
332850e27654SZeyu Fan 		} else {
332950e27654SZeyu Fan 			if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) {
333050e27654SZeyu Fan 				if (support.bits.graphics_content == 1) {
333150e27654SZeyu Fan 					cn0_cn1_value = 0;
333250e27654SZeyu Fan 				}
333350e27654SZeyu Fan 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) {
333450e27654SZeyu Fan 				if (support.bits.photo_content == 1) {
333550e27654SZeyu Fan 					cn0_cn1_value = 1;
333650e27654SZeyu Fan 				} else {
333750e27654SZeyu Fan 					cn0_cn1_value = 0;
333850e27654SZeyu Fan 					itc_value = 0;
333950e27654SZeyu Fan 				}
334050e27654SZeyu Fan 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) {
334150e27654SZeyu Fan 				if (support.bits.cinema_content == 1) {
334250e27654SZeyu Fan 					cn0_cn1_value = 2;
334350e27654SZeyu Fan 				} else {
334450e27654SZeyu Fan 					cn0_cn1_value = 0;
334550e27654SZeyu Fan 					itc_value = 0;
334650e27654SZeyu Fan 				}
334750e27654SZeyu Fan 			} else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) {
334850e27654SZeyu Fan 				if (support.bits.game_content == 1) {
334950e27654SZeyu Fan 					cn0_cn1_value = 3;
335050e27654SZeyu Fan 				} else {
335150e27654SZeyu Fan 					cn0_cn1_value = 0;
335250e27654SZeyu Fan 					itc_value = 0;
335350e27654SZeyu Fan 				}
335450e27654SZeyu Fan 			}
335550e27654SZeyu Fan 		}
3356e09b6473SAnthony Koo 		hdmi_info.bits.CN0_CN1 = cn0_cn1_value;
3357e09b6473SAnthony Koo 		hdmi_info.bits.ITC = itc_value;
33584562236bSHarry Wentland 	}
33594562236bSHarry Wentland 
3360fdf7d4f5SDillon Varone 	if (stream->qs_bit == 1) {
3361fdf7d4f5SDillon Varone 		if (color_space == COLOR_SPACE_SRGB ||
3362fdf7d4f5SDillon Varone 			color_space == COLOR_SPACE_2020_RGB_FULLRANGE)
3363fdf7d4f5SDillon Varone 			hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_FULL_RANGE;
3364fdf7d4f5SDillon Varone 		else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
3365fdf7d4f5SDillon Varone 					color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)
3366fdf7d4f5SDillon Varone 			hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_LIMITED_RANGE;
3367fdf7d4f5SDillon Varone 		else
3368fdf7d4f5SDillon Varone 			hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_DEFAULT_RANGE;
3369fdf7d4f5SDillon Varone 	} else
3370fdf7d4f5SDillon Varone 		hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_DEFAULT_RANGE;
3371fdf7d4f5SDillon Varone 
33724562236bSHarry Wentland 	/* TODO : We should handle YCC quantization */
33734562236bSHarry Wentland 	/* but we do not have matrix calculation */
3374e09b6473SAnthony Koo 	hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
337550e27654SZeyu Fan 
337615e17335SCharlene Liu 	///VIC
33774affb123SChris Park 	if (pipe_ctx->stream->timing.hdmi_vic != 0)
33784affb123SChris Park 		vic = 0;
33794fa086b9SLeo (Sunpeng) Li 	format = stream->timing.timing_3d_format;
338015e17335SCharlene Liu 	/*todo, add 3DStereo support*/
338115e17335SCharlene Liu 	if (format != TIMING_3D_FORMAT_NONE) {
338215e17335SCharlene Liu 		// Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled
33834fa086b9SLeo (Sunpeng) Li 		switch (pipe_ctx->stream->timing.hdmi_vic) {
338415e17335SCharlene Liu 		case 1:
338515e17335SCharlene Liu 			vic = 95;
338615e17335SCharlene Liu 			break;
338715e17335SCharlene Liu 		case 2:
338815e17335SCharlene Liu 			vic = 94;
338915e17335SCharlene Liu 			break;
339015e17335SCharlene Liu 		case 3:
339115e17335SCharlene Liu 			vic = 93;
339215e17335SCharlene Liu 			break;
339315e17335SCharlene Liu 		case 4:
339415e17335SCharlene Liu 			vic = 98;
339515e17335SCharlene Liu 			break;
339615e17335SCharlene Liu 		default:
339715e17335SCharlene Liu 			break;
339815e17335SCharlene Liu 		}
339915e17335SCharlene Liu 	}
3400efa02336SChris Park 	/* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/
3401e09b6473SAnthony Koo 	hdmi_info.bits.VIC0_VIC7 = vic;
3402efa02336SChris Park 	if (vic >= 128)
3403efa02336SChris Park 		hdmi_info.bits.header.version = 3;
3404efa02336SChris Park 	/* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1),
3405efa02336SChris Park 	 * the Source shall use 20 AVI InfoFrame Version 4
3406efa02336SChris Park 	 */
3407efa02336SChris Park 	if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED &&
3408efa02336SChris Park 			hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) {
3409efa02336SChris Park 		hdmi_info.bits.header.version = 4;
3410efa02336SChris Park 		hdmi_info.bits.header.length = 14;
3411efa02336SChris Park 	}
34124562236bSHarry Wentland 
3413427a60c1SChris Park 	if (rid != 0 && fr_ind != 0) {
3414427a60c1SChris Park 		hdmi_info.bits.header.version = 5;
3415427a60c1SChris Park 		hdmi_info.bits.header.length = 15;
3416427a60c1SChris Park 
3417427a60c1SChris Park 		hdmi_info.bits.FR0_FR3 = fr_ind & 0xF;
3418427a60c1SChris Park 		hdmi_info.bits.FR4 = (fr_ind >> 4) & 0x1;
3419427a60c1SChris Park 		hdmi_info.bits.RID0_RID5 = rid;
3420427a60c1SChris Park 	}
3421427a60c1SChris Park 
34224562236bSHarry Wentland 	/* pixel repetition
34234562236bSHarry Wentland 	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
34244562236bSHarry Wentland 	 * repetition start from 1 */
3425e09b6473SAnthony Koo 	hdmi_info.bits.PR0_PR3 = 0;
34264562236bSHarry Wentland 
34274562236bSHarry Wentland 	/* Bar Info
34284562236bSHarry Wentland 	 * barTop:    Line Number of End of Top Bar.
34294562236bSHarry Wentland 	 * barBottom: Line Number of Start of Bottom Bar.
34304562236bSHarry Wentland 	 * barLeft:   Pixel Number of End of Left Bar.
34314562236bSHarry Wentland 	 * barRight:  Pixel Number of Start of Right Bar. */
3432e09b6473SAnthony Koo 	hdmi_info.bits.bar_top = stream->timing.v_border_top;
3433e09b6473SAnthony Koo 	hdmi_info.bits.bar_bottom = (stream->timing.v_total
34344fa086b9SLeo (Sunpeng) Li 			- stream->timing.v_border_bottom + 1);
3435e09b6473SAnthony Koo 	hdmi_info.bits.bar_left  = stream->timing.h_border_left;
3436e09b6473SAnthony Koo 	hdmi_info.bits.bar_right = (stream->timing.h_total
34374fa086b9SLeo (Sunpeng) Li 			- stream->timing.h_border_right + 1);
34384562236bSHarry Wentland 
34392f482c4fSChris Park     /* Additional Colorimetry Extension
34402f482c4fSChris Park      * Used in conduction with C0-C1 and EC0-EC2
34412f482c4fSChris Park      * 0 = DCI-P3 RGB (D65)
34422f482c4fSChris Park      * 1 = DCI-P3 RGB (theater)
34432f482c4fSChris Park      */
34442f482c4fSChris Park 	hdmi_info.bits.ACE0_ACE3 = 0;
34452f482c4fSChris Park 
34464562236bSHarry Wentland 	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
3447e09b6473SAnthony Koo 	check_sum = &hdmi_info.packet_raw_data.sb[0];
3448e8d726b7SReza Amini 
3449efa02336SChris Park 	*check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version;
34504562236bSHarry Wentland 
3451efa02336SChris Park 	for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++)
3452e09b6473SAnthony Koo 		*check_sum += hdmi_info.packet_raw_data.sb[byte_index];
34534562236bSHarry Wentland 
34544562236bSHarry Wentland 	/* one byte complement */
34554562236bSHarry Wentland 	*check_sum = (uint8_t) (0x100 - *check_sum);
34564562236bSHarry Wentland 
34574562236bSHarry Wentland 	/* Store in hw_path_mode */
3458e09b6473SAnthony Koo 	info_packet->hb0 = hdmi_info.packet_raw_data.hb0;
3459e09b6473SAnthony Koo 	info_packet->hb1 = hdmi_info.packet_raw_data.hb1;
3460e09b6473SAnthony Koo 	info_packet->hb2 = hdmi_info.packet_raw_data.hb2;
34614562236bSHarry Wentland 
3462e09b6473SAnthony Koo 	for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++)
3463e09b6473SAnthony Koo 		info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index];
34644562236bSHarry Wentland 
34654562236bSHarry Wentland 	info_packet->valid = true;
34664562236bSHarry Wentland }
34674562236bSHarry Wentland 
set_vendor_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)34686e4d6beeSTony Cheng static void set_vendor_info_packet(
3469e09b6473SAnthony Koo 		struct dc_info_packet *info_packet,
34700971c40eSHarry Wentland 		struct dc_stream_state *stream)
34714562236bSHarry Wentland {
3472ecd0136bSHarmanprit Tatla 	/* SPD info packet for FreeSync */
347315e17335SCharlene Liu 
3474ecd0136bSHarmanprit Tatla 	/* Check if Freesync is supported. Return if false. If true,
3475ecd0136bSHarmanprit Tatla 	 * set the corresponding bit in the info packet
3476ecd0136bSHarmanprit Tatla 	 */
3477ecd0136bSHarmanprit Tatla 	if (!stream->vsp_infopacket.valid)
34784562236bSHarry Wentland 		return;
34794562236bSHarry Wentland 
3480ecd0136bSHarmanprit Tatla 	*info_packet = stream->vsp_infopacket;
34814562236bSHarry Wentland }
34824562236bSHarry Wentland 
set_spd_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)34836e4d6beeSTony Cheng static void set_spd_info_packet(
3484e09b6473SAnthony Koo 		struct dc_info_packet *info_packet,
34850971c40eSHarry Wentland 		struct dc_stream_state *stream)
34864562236bSHarry Wentland {
34874562236bSHarry Wentland 	/* SPD info packet for FreeSync */
34884562236bSHarry Wentland 
34894562236bSHarry Wentland 	/* Check if Freesync is supported. Return if false. If true,
34904562236bSHarry Wentland 	 * set the corresponding bit in the info packet
34914562236bSHarry Wentland 	 */
349298e6436dSAnthony Koo 	if (!stream->vrr_infopacket.valid)
34934562236bSHarry Wentland 		return;
34944562236bSHarry Wentland 
349598e6436dSAnthony Koo 	*info_packet = stream->vrr_infopacket;
34964562236bSHarry Wentland }
34974562236bSHarry Wentland 
set_hdr_static_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)34981646a6feSAndrew Wong static void set_hdr_static_info_packet(
3499e09b6473SAnthony Koo 		struct dc_info_packet *info_packet,
35000971c40eSHarry Wentland 		struct dc_stream_state *stream)
35011646a6feSAndrew Wong {
35020eeef690SAnthony Koo 	/* HDR Static Metadata info packet for HDR10 */
35031646a6feSAndrew Wong 
3504a10dc97aSKrunoslav Kovac 	if (!stream->hdr_static_metadata.valid ||
3505a10dc97aSKrunoslav Kovac 			stream->use_dynamic_meta)
350610bff005SYongqiang Sun 		return;
350710bff005SYongqiang Sun 
35080eeef690SAnthony Koo 	*info_packet = stream->hdr_static_metadata;
35091646a6feSAndrew Wong }
35101646a6feSAndrew Wong 
set_vsc_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)35116e4d6beeSTony Cheng static void set_vsc_info_packet(
3512e09b6473SAnthony Koo 		struct dc_info_packet *info_packet,
35130971c40eSHarry Wentland 		struct dc_stream_state *stream)
35144562236bSHarry Wentland {
35151336926fSAlvin lee 	if (!stream->vsc_infopacket.valid)
35164562236bSHarry Wentland 		return;
35174562236bSHarry Wentland 
35181336926fSAlvin lee 	*info_packet = stream->vsc_infopacket;
35194562236bSHarry Wentland }
set_hfvs_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)35202bbb54bbSAhmad Othman static void set_hfvs_info_packet(
35212bbb54bbSAhmad Othman 		struct dc_info_packet *info_packet,
35222bbb54bbSAhmad Othman 		struct dc_stream_state *stream)
35232bbb54bbSAhmad Othman {
35242bbb54bbSAhmad Othman 	if (!stream->hfvsif_infopacket.valid)
35252bbb54bbSAhmad Othman 		return;
35262bbb54bbSAhmad Othman 
35272bbb54bbSAhmad Othman 	*info_packet = stream->hfvsif_infopacket;
35282bbb54bbSAhmad Othman }
35294562236bSHarry Wentland 
adaptive_sync_override_dp_info_packets_sdp_line_num(const struct dc_crtc_timing * timing,struct enc_sdp_line_num * sdp_line_num,struct _vcs_dpi_display_pipe_dest_params_st * pipe_dlg_param)3530e95afc1cSSung Joon Kim static void adaptive_sync_override_dp_info_packets_sdp_line_num(
3531e95afc1cSSung Joon Kim 		const struct dc_crtc_timing *timing,
3532e95afc1cSSung Joon Kim 		struct enc_sdp_line_num *sdp_line_num,
3533e95afc1cSSung Joon Kim 		struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
3534e95afc1cSSung Joon Kim {
3535e95afc1cSSung Joon Kim 	uint32_t asic_blank_start = 0;
3536e95afc1cSSung Joon Kim 	uint32_t asic_blank_end   = 0;
3537e95afc1cSSung Joon Kim 	uint32_t v_update = 0;
3538e95afc1cSSung Joon Kim 
3539e95afc1cSSung Joon Kim 	const struct dc_crtc_timing *tg = timing;
3540e95afc1cSSung Joon Kim 
3541e95afc1cSSung Joon Kim 	/* blank_start = frame end - front porch */
3542e95afc1cSSung Joon Kim 	asic_blank_start = tg->v_total - tg->v_front_porch;
3543e95afc1cSSung Joon Kim 
3544e95afc1cSSung Joon Kim 	/* blank_end = blank_start - active */
3545e95afc1cSSung Joon Kim 	asic_blank_end = (asic_blank_start - tg->v_border_bottom -
3546e95afc1cSSung Joon Kim 						tg->v_addressable - tg->v_border_top);
3547e95afc1cSSung Joon Kim 
3548e95afc1cSSung Joon Kim 	if (pipe_dlg_param->vstartup_start > asic_blank_end) {
3549e95afc1cSSung Joon Kim 		v_update = (tg->v_total - (pipe_dlg_param->vstartup_start - asic_blank_end));
3550e95afc1cSSung Joon Kim 		sdp_line_num->adaptive_sync_line_num_valid = true;
3551e95afc1cSSung Joon Kim 		sdp_line_num->adaptive_sync_line_num = (tg->v_total - v_update - 1);
3552e95afc1cSSung Joon Kim 	} else {
3553e95afc1cSSung Joon Kim 		sdp_line_num->adaptive_sync_line_num_valid = false;
3554e95afc1cSSung Joon Kim 		sdp_line_num->adaptive_sync_line_num = 0;
3555e95afc1cSSung Joon Kim 	}
3556e95afc1cSSung Joon Kim }
3557e95afc1cSSung Joon Kim 
set_adaptive_sync_info_packet(struct dc_info_packet * info_packet,const struct dc_stream_state * stream,struct encoder_info_frame * info_frame,struct _vcs_dpi_display_pipe_dest_params_st * pipe_dlg_param)3558e95afc1cSSung Joon Kim static void set_adaptive_sync_info_packet(
3559e95afc1cSSung Joon Kim 		struct dc_info_packet *info_packet,
3560e95afc1cSSung Joon Kim 		const struct dc_stream_state *stream,
3561e95afc1cSSung Joon Kim 		struct encoder_info_frame *info_frame,
3562e95afc1cSSung Joon Kim 		struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
3563e95afc1cSSung Joon Kim {
3564e95afc1cSSung Joon Kim 	if (!stream->adaptive_sync_infopacket.valid)
3565e95afc1cSSung Joon Kim 		return;
3566e95afc1cSSung Joon Kim 
3567e95afc1cSSung Joon Kim 	adaptive_sync_override_dp_info_packets_sdp_line_num(
3568e95afc1cSSung Joon Kim 			&stream->timing,
3569e95afc1cSSung Joon Kim 			&info_frame->sdp_line_num,
3570e95afc1cSSung Joon Kim 			pipe_dlg_param);
3571e95afc1cSSung Joon Kim 
3572e95afc1cSSung Joon Kim 	*info_packet = stream->adaptive_sync_infopacket;
3573e95afc1cSSung Joon Kim }
35749a4c9de4SAhmad Othman 
set_vtem_info_packet(struct dc_info_packet * info_packet,struct dc_stream_state * stream)35759a4c9de4SAhmad Othman static void set_vtem_info_packet(
35769a4c9de4SAhmad Othman 		struct dc_info_packet *info_packet,
35779a4c9de4SAhmad Othman 		struct dc_stream_state *stream)
35789a4c9de4SAhmad Othman {
35799a4c9de4SAhmad Othman 	if (!stream->vtem_infopacket.valid)
35809a4c9de4SAhmad Othman 		return;
35819a4c9de4SAhmad Othman 
35829a4c9de4SAhmad Othman 	*info_packet = stream->vtem_infopacket;
35839a4c9de4SAhmad Othman }
35849a4c9de4SAhmad Othman 
dc_resource_state_destruct(struct dc_state * context)3585f36cc577SBhawanpreet Lakha void dc_resource_state_destruct(struct dc_state *context)
35864562236bSHarry Wentland {
35874562236bSHarry Wentland 	int i, j;
35884562236bSHarry Wentland 
3589ab2541b6SAric Cyr 	for (i = 0; i < context->stream_count; i++) {
35903be5262eSHarry Wentland 		for (j = 0; j < context->stream_status[i].plane_count; j++)
35913be5262eSHarry Wentland 			dc_plane_state_release(
35923be5262eSHarry Wentland 				context->stream_status[i].plane_states[j]);
35934562236bSHarry Wentland 
35943be5262eSHarry Wentland 		context->stream_status[i].plane_count = 0;
35954fa086b9SLeo (Sunpeng) Li 		dc_stream_release(context->streams[i]);
3596ab2541b6SAric Cyr 		context->streams[i] = NULL;
35974562236bSHarry Wentland 	}
35985728d5e5SPaul Wu 	context->stream_count = 0;
35994562236bSHarry Wentland }
36004562236bSHarry Wentland 
dc_resource_state_copy_construct(const struct dc_state * src_ctx,struct dc_state * dst_ctx)3601f36cc577SBhawanpreet Lakha void dc_resource_state_copy_construct(
3602608ac7bbSJerry Zuo 		const struct dc_state *src_ctx,
3603608ac7bbSJerry Zuo 		struct dc_state *dst_ctx)
36044562236bSHarry Wentland {
36054562236bSHarry Wentland 	int i, j;
36068ee5702aSDave Airlie 	struct kref refcount = dst_ctx->refcount;
36074562236bSHarry Wentland 
36084562236bSHarry Wentland 	*dst_ctx = *src_ctx;
36094562236bSHarry Wentland 
3610a2b8659dSTony Cheng 	for (i = 0; i < MAX_PIPES; i++) {
36114562236bSHarry Wentland 		struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
36124562236bSHarry Wentland 
36134562236bSHarry Wentland 		if (cur_pipe->top_pipe)
36144562236bSHarry Wentland 			cur_pipe->top_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
36154562236bSHarry Wentland 
36164562236bSHarry Wentland 		if (cur_pipe->bottom_pipe)
36174562236bSHarry Wentland 			cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
3618b1f6d01cSDmytro Laktyushkin 
3619b1f6d01cSDmytro Laktyushkin 		if (cur_pipe->next_odm_pipe)
3620b1f6d01cSDmytro Laktyushkin 			cur_pipe->next_odm_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
3621b1f6d01cSDmytro Laktyushkin 
3622b1f6d01cSDmytro Laktyushkin 		if (cur_pipe->prev_odm_pipe)
3623b1f6d01cSDmytro Laktyushkin 			cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
36244562236bSHarry Wentland 	}
36254562236bSHarry Wentland 
3626ab2541b6SAric Cyr 	for (i = 0; i < dst_ctx->stream_count; i++) {
36274fa086b9SLeo (Sunpeng) Li 		dc_stream_retain(dst_ctx->streams[i]);
36283be5262eSHarry Wentland 		for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++)
36293be5262eSHarry Wentland 			dc_plane_state_retain(
36303be5262eSHarry Wentland 				dst_ctx->stream_status[i].plane_states[j]);
36314562236bSHarry Wentland 	}
36329a3afbb3SAndrey Grodzovsky 
36339a3afbb3SAndrey Grodzovsky 	/* context refcount should not be overridden */
36348ee5702aSDave Airlie 	dst_ctx->refcount = refcount;
36359a3afbb3SAndrey Grodzovsky 
36364562236bSHarry Wentland }
36374562236bSHarry Wentland 
dc_resource_find_first_free_pll(struct resource_context * res_ctx,const struct resource_pool * pool)36384562236bSHarry Wentland struct clock_source *dc_resource_find_first_free_pll(
3639a2b8659dSTony Cheng 		struct resource_context *res_ctx,
3640a2b8659dSTony Cheng 		const struct resource_pool *pool)
36414562236bSHarry Wentland {
36424562236bSHarry Wentland 	int i;
36434562236bSHarry Wentland 
3644a2b8659dSTony Cheng 	for (i = 0; i < pool->clk_src_count; ++i) {
36454562236bSHarry Wentland 		if (res_ctx->clock_source_ref_count[i] == 0)
3646a2b8659dSTony Cheng 			return pool->clock_sources[i];
36474562236bSHarry Wentland 	}
36484562236bSHarry Wentland 
36494562236bSHarry Wentland 	return NULL;
36504562236bSHarry Wentland }
36514562236bSHarry Wentland 
resource_build_info_frame(struct pipe_ctx * pipe_ctx)36524562236bSHarry Wentland void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
36534562236bSHarry Wentland {
36544562236bSHarry Wentland 	enum signal_type signal = SIGNAL_TYPE_NONE;
365596c50c0dSHarry Wentland 	struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame;
36564562236bSHarry Wentland 
36574562236bSHarry Wentland 	/* default all packets to invalid */
36586e4d6beeSTony Cheng 	info->avi.valid = false;
36596e4d6beeSTony Cheng 	info->gamut.valid = false;
36606e4d6beeSTony Cheng 	info->vendor.valid = false;
3661630e3573SJeff Smith 	info->spd.valid = false;
36626e4d6beeSTony Cheng 	info->hdrsmd.valid = false;
36636e4d6beeSTony Cheng 	info->vsc.valid = false;
36642bbb54bbSAhmad Othman 	info->hfvsif.valid = false;
36659a4c9de4SAhmad Othman 	info->vtem.valid = false;
3666e95afc1cSSung Joon Kim 	info->adaptive_sync.valid = false;
36674562236bSHarry Wentland 	signal = pipe_ctx->stream->signal;
36684562236bSHarry Wentland 
36694562236bSHarry Wentland 	/* HDMi and DP have different info packets*/
36704562236bSHarry Wentland 	if (dc_is_hdmi_signal(signal)) {
36716e4d6beeSTony Cheng 		set_avi_info_frame(&info->avi, pipe_ctx);
36726e4d6beeSTony Cheng 
36736e4d6beeSTony Cheng 		set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
36742bbb54bbSAhmad Othman 		set_hfvs_info_packet(&info->hfvsif, pipe_ctx->stream);
36759a4c9de4SAhmad Othman 		set_vtem_info_packet(&info->vtem, pipe_ctx->stream);
36766e4d6beeSTony Cheng 
36776e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
36786e4d6beeSTony Cheng 
367956ef6ed9SAnthony Koo 		set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
36806e4d6beeSTony Cheng 
3681a33fa99dSHarry Wentland 	} else if (dc_is_dp_signal(signal)) {
36826e4d6beeSTony Cheng 		set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
36836e4d6beeSTony Cheng 
36846e4d6beeSTony Cheng 		set_spd_info_packet(&info->spd, pipe_ctx->stream);
36856e4d6beeSTony Cheng 
368656ef6ed9SAnthony Koo 		set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
3687e95afc1cSSung Joon Kim 		set_adaptive_sync_info_packet(&info->adaptive_sync,
3688e95afc1cSSung Joon Kim 										pipe_ctx->stream,
3689e95afc1cSSung Joon Kim 										info,
3690e95afc1cSSung Joon Kim 										&pipe_ctx->pipe_dlg_param);
3691a33fa99dSHarry Wentland 	}
36924562236bSHarry Wentland 
36936e4d6beeSTony Cheng 	patch_gamut_packet_checksum(&info->gamut);
36944562236bSHarry Wentland }
36954562236bSHarry Wentland 
resource_map_clock_resources(const struct dc * dc,struct dc_state * context,struct dc_stream_state * stream)36964562236bSHarry Wentland enum dc_status resource_map_clock_resources(
3697fb3466a4SBhawanpreet Lakha 		const struct dc  *dc,
3698608ac7bbSJerry Zuo 		struct dc_state *context,
36991dc90497SAndrey Grodzovsky 		struct dc_stream_state *stream)
37004562236bSHarry Wentland {
37014562236bSHarry Wentland 	/* acquire new resources */
37021dc90497SAndrey Grodzovsky 	const struct resource_pool *pool = dc->res_pool;
370353f32880SWenjing Liu 	struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(
37041dc90497SAndrey Grodzovsky 				&context->res_ctx, stream);
37054562236bSHarry Wentland 
37061dc90497SAndrey Grodzovsky 	if (!pipe_ctx)
37071dc90497SAndrey Grodzovsky 		return DC_ERROR_UNEXPECTED;
37084562236bSHarry Wentland 
37094562236bSHarry Wentland 	if (dc_is_dp_signal(pipe_ctx->stream->signal)
37104562236bSHarry Wentland 		|| pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
3711a2b8659dSTony Cheng 		pipe_ctx->clock_source = pool->dp_clock_source;
37124562236bSHarry Wentland 	else {
37134562236bSHarry Wentland 		pipe_ctx->clock_source = NULL;
37144562236bSHarry Wentland 
3715fb3466a4SBhawanpreet Lakha 		if (!dc->config.disable_disp_pll_sharing)
37164ed4e51bSMikita Lipski 			pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing(
37174562236bSHarry Wentland 				&context->res_ctx,
37184562236bSHarry Wentland 				pipe_ctx);
37194562236bSHarry Wentland 
37204562236bSHarry Wentland 		if (pipe_ctx->clock_source == NULL)
37214562236bSHarry Wentland 			pipe_ctx->clock_source =
3722a2b8659dSTony Cheng 				dc_resource_find_first_free_pll(
3723a2b8659dSTony Cheng 					&context->res_ctx,
3724a2b8659dSTony Cheng 					pool);
37254562236bSHarry Wentland 	}
37264562236bSHarry Wentland 
37274562236bSHarry Wentland 	if (pipe_ctx->clock_source == NULL)
37284562236bSHarry Wentland 		return DC_NO_CLOCK_SOURCE_RESOURCE;
37294562236bSHarry Wentland 
37304562236bSHarry Wentland 	resource_reference_clock_source(
3731a2b8659dSTony Cheng 		&context->res_ctx, pool,
37324562236bSHarry Wentland 		pipe_ctx->clock_source);
37334562236bSHarry Wentland 
37344562236bSHarry Wentland 	return DC_OK;
37354562236bSHarry Wentland }
37364562236bSHarry Wentland 
37374562236bSHarry Wentland /*
37384562236bSHarry Wentland  * Note: We need to disable output if clock sources change,
37394562236bSHarry Wentland  * since bios does optimization and doesn't apply if changing
37404562236bSHarry Wentland  * PHY when not already disabled.
37414562236bSHarry Wentland  */
pipe_need_reprogram(struct pipe_ctx * pipe_ctx_old,struct pipe_ctx * pipe_ctx)37424562236bSHarry Wentland bool pipe_need_reprogram(
37434562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx_old,
37444562236bSHarry Wentland 		struct pipe_ctx *pipe_ctx)
37454562236bSHarry Wentland {
3746cfe4645eSDmytro Laktyushkin 	if (!pipe_ctx_old->stream)
3747cfe4645eSDmytro Laktyushkin 		return false;
3748cfe4645eSDmytro Laktyushkin 
37494562236bSHarry Wentland 	if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
37504562236bSHarry Wentland 		return true;
37514562236bSHarry Wentland 
37524562236bSHarry Wentland 	if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
37534562236bSHarry Wentland 		return true;
37544562236bSHarry Wentland 
3755afaacef4SHarry Wentland 	if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio)
37564562236bSHarry Wentland 		return true;
37574562236bSHarry Wentland 
37584562236bSHarry Wentland 	if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
37594562236bSHarry Wentland 			&& pipe_ctx_old->stream != pipe_ctx->stream)
37604562236bSHarry Wentland 		return true;
37614562236bSHarry Wentland 
37628e9c4c8cSHarry Wentland 	if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc)
37634562236bSHarry Wentland 		return true;
37644562236bSHarry Wentland 
37653306ba4bSArnd Bergmann 	if (dc_is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
37664562236bSHarry Wentland 		return true;
37674562236bSHarry Wentland 
37681e7e86c4SSamson Tam 	if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off)
37691e7e86c4SSamson Tam 		return true;
37701e7e86c4SSamson Tam 
3771eed928dcSCharlene Liu 	if (false == pipe_ctx_old->stream->link->link_state_valid &&
3772eed928dcSCharlene Liu 		false == pipe_ctx_old->stream->dpms_off)
3773eed928dcSCharlene Liu 		return true;
3774eed928dcSCharlene Liu 
377514e49bb3SNikola Cornij 	if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc)
377614e49bb3SNikola Cornij 		return true;
377714e49bb3SNikola Cornij 
3778f01ee019SFangzhi Zuo 	if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc)
3779f01ee019SFangzhi Zuo 		return true;
37806dd8931bSWenjing Liu 	if (pipe_ctx_old->link_res.hpo_dp_link_enc != pipe_ctx->link_res.hpo_dp_link_enc)
37816dd8931bSWenjing Liu 		return true;
3782f01ee019SFangzhi Zuo 
3783f42ef862SJimmy Kizito 	/* DIG link encoder resource assignment for stream changed. */
37840d4b4253SJimmy Kizito 	if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) {
37850d4b4253SJimmy Kizito 		bool need_reprogram = false;
37860d4b4253SJimmy Kizito 		struct dc *dc = pipe_ctx_old->stream->ctx->dc;
37876366b003SJimmy Kizito 		struct link_encoder *link_enc_prev =
37886366b003SJimmy Kizito 			link_enc_cfg_get_link_enc_used_by_stream_current(dc, pipe_ctx_old->stream);
37890d4b4253SJimmy Kizito 
37906366b003SJimmy Kizito 		if (link_enc_prev != pipe_ctx->stream->link_enc)
37910d4b4253SJimmy Kizito 			need_reprogram = true;
37920d4b4253SJimmy Kizito 
37930d4b4253SJimmy Kizito 		return need_reprogram;
37940d4b4253SJimmy Kizito 	}
3795f42ef862SJimmy Kizito 
37964562236bSHarry Wentland 	return false;
37974562236bSHarry Wentland }
3798529cad0fSDing Wang 
resource_build_bit_depth_reduction_params(struct dc_stream_state * stream,struct bit_depth_reduction_params * fmt_bit_depth)37990971c40eSHarry Wentland void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
3800529cad0fSDing Wang 		struct bit_depth_reduction_params *fmt_bit_depth)
3801529cad0fSDing Wang {
38024fa086b9SLeo (Sunpeng) Li 	enum dc_dither_option option = stream->dither_option;
3803529cad0fSDing Wang 	enum dc_pixel_encoding pixel_encoding =
38044fa086b9SLeo (Sunpeng) Li 			stream->timing.pixel_encoding;
3805529cad0fSDing Wang 
3806529cad0fSDing Wang 	memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
3807529cad0fSDing Wang 
3808603767f9STony Cheng 	if (option == DITHER_OPTION_DEFAULT) {
3809603767f9STony Cheng 		switch (stream->timing.display_color_depth) {
3810603767f9STony Cheng 		case COLOR_DEPTH_666:
3811603767f9STony Cheng 			option = DITHER_OPTION_SPATIAL6;
3812603767f9STony Cheng 			break;
3813603767f9STony Cheng 		case COLOR_DEPTH_888:
3814603767f9STony Cheng 			option = DITHER_OPTION_SPATIAL8;
3815603767f9STony Cheng 			break;
3816603767f9STony Cheng 		case COLOR_DEPTH_101010:
3817603767f9STony Cheng 			option = DITHER_OPTION_SPATIAL10;
3818603767f9STony Cheng 			break;
3819603767f9STony Cheng 		default:
3820603767f9STony Cheng 			option = DITHER_OPTION_DISABLE;
3821603767f9STony Cheng 		}
3822603767f9STony Cheng 	}
3823603767f9STony Cheng 
3824529cad0fSDing Wang 	if (option == DITHER_OPTION_DISABLE)
3825529cad0fSDing Wang 		return;
3826529cad0fSDing Wang 
3827529cad0fSDing Wang 	if (option == DITHER_OPTION_TRUN6) {
3828529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
3829529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 0;
3830529cad0fSDing Wang 	} else if (option == DITHER_OPTION_TRUN8 ||
3831529cad0fSDing Wang 			option == DITHER_OPTION_TRUN8_SPATIAL6 ||
3832529cad0fSDing Wang 			option == DITHER_OPTION_TRUN8_FM6) {
3833529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
3834529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 1;
3835529cad0fSDing Wang 	} else if (option == DITHER_OPTION_TRUN10        ||
3836529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL6   ||
3837529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8   ||
3838529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_FM8     ||
3839529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_FM6     ||
3840529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
3841529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
3842529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
3843529cad0fSDing Wang 	}
3844529cad0fSDing Wang 
3845529cad0fSDing Wang 	/* special case - Formatter can only reduce by 4 bits at most.
3846529cad0fSDing Wang 	 * When reducing from 12 to 6 bits,
3847529cad0fSDing Wang 	 * HW recommends we use trunc with round mode
3848529cad0fSDing Wang 	 * (if we did nothing, trunc to 10 bits would be used)
3849529cad0fSDing Wang 	 * note that any 12->10 bit reduction is ignored prior to DCE8,
3850529cad0fSDing Wang 	 * as the input was 10 bits.
3851529cad0fSDing Wang 	 */
3852529cad0fSDing Wang 	if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM ||
3853529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL6 ||
3854529cad0fSDing Wang 			option == DITHER_OPTION_FM6) {
3855529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
3856529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
3857529cad0fSDing Wang 		fmt_bit_depth->flags.TRUNCATE_MODE = 1;
3858529cad0fSDing Wang 	}
3859529cad0fSDing Wang 
3860529cad0fSDing Wang 	/* spatial dither
3861529cad0fSDing Wang 	 * note that spatial modes 1-3 are never used
3862529cad0fSDing Wang 	 */
3863529cad0fSDing Wang 	if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM            ||
3864529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL6 ||
3865529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL6      ||
3866529cad0fSDing Wang 			option == DITHER_OPTION_TRUN8_SPATIAL6) {
3867529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
3868529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
3869529cad0fSDing Wang 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
3870529cad0fSDing Wang 		fmt_bit_depth->flags.RGB_RANDOM =
3871529cad0fSDing Wang 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
3872529cad0fSDing Wang 	} else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM            ||
3873529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL8 ||
3874529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL8_FM6        ||
3875529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8      ||
3876529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
3877529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
3878529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
3879529cad0fSDing Wang 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
3880529cad0fSDing Wang 		fmt_bit_depth->flags.RGB_RANDOM =
3881529cad0fSDing Wang 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
3882529cad0fSDing Wang 	} else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM ||
3883529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10 ||
3884529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10_FM8 ||
3885529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10_FM6) {
3886529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
3887529cad0fSDing Wang 		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
3888529cad0fSDing Wang 		fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
3889529cad0fSDing Wang 		fmt_bit_depth->flags.RGB_RANDOM =
3890529cad0fSDing Wang 				(pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
3891529cad0fSDing Wang 	}
3892529cad0fSDing Wang 
3893529cad0fSDing Wang 	if (option == DITHER_OPTION_SPATIAL6 ||
3894529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL8 ||
3895529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10) {
3896529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_RANDOM = 0;
3897529cad0fSDing Wang 	} else {
3898529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_RANDOM = 1;
3899529cad0fSDing Wang 	}
3900529cad0fSDing Wang 
3901529cad0fSDing Wang 	//////////////////////
3902529cad0fSDing Wang 	//// temporal dither
3903529cad0fSDing Wang 	//////////////////////
3904529cad0fSDing Wang 	if (option == DITHER_OPTION_FM6           ||
3905529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL8_FM6     ||
3906529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10_FM6     ||
3907529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_FM6     ||
3908529cad0fSDing Wang 			option == DITHER_OPTION_TRUN8_FM6      ||
3909529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
3910529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
3911529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0;
3912529cad0fSDing Wang 	} else if (option == DITHER_OPTION_FM8        ||
3913529cad0fSDing Wang 			option == DITHER_OPTION_SPATIAL10_FM8  ||
3914529cad0fSDing Wang 			option == DITHER_OPTION_TRUN10_FM8) {
3915529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
3916529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1;
3917529cad0fSDing Wang 	} else if (option == DITHER_OPTION_FM10) {
3918529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
3919529cad0fSDing Wang 		fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2;
3920529cad0fSDing Wang 	}
3921529cad0fSDing Wang 
3922529cad0fSDing Wang 	fmt_bit_depth->pixel_encoding = pixel_encoding;
3923529cad0fSDing Wang }
39249345d987SAndrey Grodzovsky 
dc_validate_stream(struct dc * dc,struct dc_stream_state * stream)392562c933f9SYongqiang Sun enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
39269345d987SAndrey Grodzovsky {
3927ceb3dbb4SJun Lei 	struct dc_link *link = stream->link;
39282b77dcc5SAnthony Koo 	struct timing_generator *tg = dc->res_pool->timing_generators[0];
39299345d987SAndrey Grodzovsky 	enum dc_status res = DC_OK;
39309345d987SAndrey Grodzovsky 
39314fa086b9SLeo (Sunpeng) Li 	calculate_phy_pix_clks(stream);
39329345d987SAndrey Grodzovsky 
39334fa086b9SLeo (Sunpeng) Li 	if (!tg->funcs->validate_timing(tg, &stream->timing))
39349345d987SAndrey Grodzovsky 		res = DC_FAIL_CONTROLLER_VALIDATE;
39359345d987SAndrey Grodzovsky 
3936248cbed6SEric Bernstein 	if (res == DC_OK) {
393764d283cbSJimmy Kizito 		if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
393864d283cbSJimmy Kizito 				!link->link_enc->funcs->validate_output_with_stream(
39394fa086b9SLeo (Sunpeng) Li 						link->link_enc, stream))
39409345d987SAndrey Grodzovsky 			res = DC_FAIL_ENC_VALIDATE;
3941248cbed6SEric Bernstein 	}
39429345d987SAndrey Grodzovsky 
39439345d987SAndrey Grodzovsky 	/* TODO: validate audio ASIC caps, encoder */
39449345d987SAndrey Grodzovsky 
39459345d987SAndrey Grodzovsky 	if (res == DC_OK)
394698ce7d32SWenjing Liu 		res = dc->link_srv->validate_mode_timing(stream,
39479345d987SAndrey Grodzovsky 		      link,
39484fa086b9SLeo (Sunpeng) Li 		      &stream->timing);
39499345d987SAndrey Grodzovsky 
395062c933f9SYongqiang Sun 	return res;
39519345d987SAndrey Grodzovsky }
3952792671d7SAndrey Grodzovsky 
dc_validate_plane(struct dc * dc,const struct dc_plane_state * plane_state)395362c933f9SYongqiang Sun enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state)
3954792671d7SAndrey Grodzovsky {
395562c933f9SYongqiang Sun 	enum dc_status res = DC_OK;
395662c933f9SYongqiang Sun 
395794e587b8SAric Cyr 	/* check if surface has invalid dimensions */
395894e587b8SAric Cyr 	if (plane_state->src_rect.width == 0 || plane_state->src_rect.height == 0 ||
395994e587b8SAric Cyr 		plane_state->dst_rect.width == 0 || plane_state->dst_rect.height == 0)
396094e587b8SAric Cyr 		return DC_FAIL_SURFACE_VALIDATE;
396194e587b8SAric Cyr 
3962792671d7SAndrey Grodzovsky 	/* TODO For now validates pixel format only */
39638e7095b9SDmytro Laktyushkin 	if (dc->res_pool->funcs->validate_plane)
396462c933f9SYongqiang Sun 		return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps);
3965792671d7SAndrey Grodzovsky 
396662c933f9SYongqiang Sun 	return res;
3967792671d7SAndrey Grodzovsky }
396874eac5f3SSu Sung Chung 
resource_pixel_format_to_bpp(enum surface_pixel_format format)396974eac5f3SSu Sung Chung unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
397074eac5f3SSu Sung Chung {
397174eac5f3SSu Sung Chung 	switch (format) {
397274eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
397374eac5f3SSu Sung Chung 		return 8;
397474eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
397574eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
397674eac5f3SSu Sung Chung 		return 12;
397774eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
397874eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
397974eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
398074eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
398174eac5f3SSu Sung Chung 		return 16;
398274eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
398374eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
398474eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
398574eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
398674eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
39875dba4991SBhawanpreet Lakha 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
39885dba4991SBhawanpreet Lakha 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
398974eac5f3SSu Sung Chung 		return 32;
399074eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
3991050cd3d6SMario Kleiner 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
399274eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
399374eac5f3SSu Sung Chung 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
399474eac5f3SSu Sung Chung 		return 64;
399574eac5f3SSu Sung Chung 	default:
399674eac5f3SSu Sung Chung 		ASSERT_CRITICAL(false);
399774eac5f3SSu Sung Chung 		return -1;
399874eac5f3SSu Sung Chung 	}
399974eac5f3SSu Sung Chung }
get_max_audio_sample_rate(struct audio_mode * modes)40003ab4cc65SCharlene Liu static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
40013ab4cc65SCharlene Liu {
40023ab4cc65SCharlene Liu 	if (modes) {
40033ab4cc65SCharlene Liu 		if (modes->sample_rates.rate.RATE_192)
40043ab4cc65SCharlene Liu 			return 192000;
40053ab4cc65SCharlene Liu 		if (modes->sample_rates.rate.RATE_176_4)
40063ab4cc65SCharlene Liu 			return 176400;
40073ab4cc65SCharlene Liu 		if (modes->sample_rates.rate.RATE_96)
40083ab4cc65SCharlene Liu 			return 96000;
40093ab4cc65SCharlene Liu 		if (modes->sample_rates.rate.RATE_88_2)
40103ab4cc65SCharlene Liu 			return 88200;
40113ab4cc65SCharlene Liu 		if (modes->sample_rates.rate.RATE_48)
40123ab4cc65SCharlene Liu 			return 48000;
40133ab4cc65SCharlene Liu 		if (modes->sample_rates.rate.RATE_44_1)
40143ab4cc65SCharlene Liu 			return 44100;
40153ab4cc65SCharlene Liu 		if (modes->sample_rates.rate.RATE_32)
40163ab4cc65SCharlene Liu 			return 32000;
40173ab4cc65SCharlene Liu 	}
40183ab4cc65SCharlene Liu 	/*original logic when no audio info*/
40193ab4cc65SCharlene Liu 	return 441000;
40203ab4cc65SCharlene Liu }
40213ab4cc65SCharlene Liu 
get_audio_check(struct audio_info * aud_modes,struct audio_check * audio_chk)40223ab4cc65SCharlene Liu void get_audio_check(struct audio_info *aud_modes,
40233ab4cc65SCharlene Liu 	struct audio_check *audio_chk)
40243ab4cc65SCharlene Liu {
40253ab4cc65SCharlene Liu 	unsigned int i;
40263ab4cc65SCharlene Liu 	unsigned int max_sample_rate = 0;
40273ab4cc65SCharlene Liu 
40283ab4cc65SCharlene Liu 	if (aud_modes) {
40293ab4cc65SCharlene Liu 		audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/
40303ab4cc65SCharlene Liu 
40313ab4cc65SCharlene Liu 		audio_chk->max_audiosample_rate = 0;
40323ab4cc65SCharlene Liu 		for (i = 0; i < aud_modes->mode_count; i++) {
40333ab4cc65SCharlene Liu 			max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]);
40343ab4cc65SCharlene Liu 			if (audio_chk->max_audiosample_rate < max_sample_rate)
40353ab4cc65SCharlene Liu 				audio_chk->max_audiosample_rate = max_sample_rate;
40363ab4cc65SCharlene Liu 			/*dts takes the same as type 2: AP = 0.25*/
40373ab4cc65SCharlene Liu 		}
40383ab4cc65SCharlene Liu 		/*check which one take more bandwidth*/
40393ab4cc65SCharlene Liu 		if (audio_chk->max_audiosample_rate > 192000)
40403ab4cc65SCharlene Liu 			audio_chk->audio_packet_type = 0x9;/*AP =1*/
40413ab4cc65SCharlene Liu 		audio_chk->acat = 0;/*not support*/
40423ab4cc65SCharlene Liu 	}
40433ab4cc65SCharlene Liu }
40443ab4cc65SCharlene Liu 
get_temp_hpo_dp_link_enc(const struct resource_context * res_ctx,const struct resource_pool * const pool,const struct dc_link * link)40452426d71cSWenjing Liu static struct hpo_dp_link_encoder *get_temp_hpo_dp_link_enc(
40466dd8931bSWenjing Liu 		const struct resource_context *res_ctx,
40472426d71cSWenjing Liu 		const struct resource_pool *const pool,
40486dd8931bSWenjing Liu 		const struct dc_link *link)
4049f01ee019SFangzhi Zuo {
40506dd8931bSWenjing Liu 	struct hpo_dp_link_encoder *hpo_dp_link_enc = NULL;
40516dd8931bSWenjing Liu 	int enc_index;
4052f01ee019SFangzhi Zuo 
40536dd8931bSWenjing Liu 	enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, link);
4054f01ee019SFangzhi Zuo 
40556dd8931bSWenjing Liu 	if (enc_index < 0)
40566dd8931bSWenjing Liu 		enc_index = find_free_hpo_dp_link_enc(res_ctx, pool);
4057f01ee019SFangzhi Zuo 
40586dd8931bSWenjing Liu 	if (enc_index >= 0)
40596dd8931bSWenjing Liu 		hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index];
40606dd8931bSWenjing Liu 
40616dd8931bSWenjing Liu 	return hpo_dp_link_enc;
4062f01ee019SFangzhi Zuo }
4063a896f870SMeenakshikumar Somasundaram 
get_temp_dp_link_res(struct dc_link * link,struct link_resource * link_res,struct dc_link_settings * link_settings)40642426d71cSWenjing Liu bool get_temp_dp_link_res(struct dc_link *link,
40652426d71cSWenjing Liu 		struct link_resource *link_res,
40662426d71cSWenjing Liu 		struct dc_link_settings *link_settings)
40672426d71cSWenjing Liu {
40682426d71cSWenjing Liu 	const struct dc *dc  = link->dc;
40692426d71cSWenjing Liu 	const struct resource_context *res_ctx = &dc->current_state->res_ctx;
40702426d71cSWenjing Liu 
40712426d71cSWenjing Liu 	memset(link_res, 0, sizeof(*link_res));
40722426d71cSWenjing Liu 
407398ce7d32SWenjing Liu 	if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
40742426d71cSWenjing Liu 		link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx,
40752426d71cSWenjing Liu 				dc->res_pool, link);
40762426d71cSWenjing Liu 		if (!link_res->hpo_dp_link_enc)
40772426d71cSWenjing Liu 			return false;
40782426d71cSWenjing Liu 	}
40792426d71cSWenjing Liu 	return true;
40802426d71cSWenjing Liu }
40812426d71cSWenjing Liu 
reset_syncd_pipes_from_disabled_pipes(struct dc * dc,struct dc_state * context)4082a896f870SMeenakshikumar Somasundaram void reset_syncd_pipes_from_disabled_pipes(struct dc *dc,
4083a896f870SMeenakshikumar Somasundaram 		struct dc_state *context)
4084a896f870SMeenakshikumar Somasundaram {
4085a896f870SMeenakshikumar Somasundaram 	int i, j;
4086a896f870SMeenakshikumar Somasundaram 	struct pipe_ctx *pipe_ctx_old, *pipe_ctx, *pipe_ctx_syncd;
4087a896f870SMeenakshikumar Somasundaram 
4088a896f870SMeenakshikumar Somasundaram 	/* If pipe backend is reset, need to reset pipe syncd status */
4089a896f870SMeenakshikumar Somasundaram 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
4090a896f870SMeenakshikumar Somasundaram 		pipe_ctx_old =	&dc->current_state->res_ctx.pipe_ctx[i];
4091a896f870SMeenakshikumar Somasundaram 		pipe_ctx = &context->res_ctx.pipe_ctx[i];
4092a896f870SMeenakshikumar Somasundaram 
409353f32880SWenjing Liu 		if (!resource_is_pipe_type(pipe_ctx_old, OTG_MASTER))
4094a896f870SMeenakshikumar Somasundaram 			continue;
4095a896f870SMeenakshikumar Somasundaram 
4096a896f870SMeenakshikumar Somasundaram 		if (!pipe_ctx->stream ||
4097a896f870SMeenakshikumar Somasundaram 				pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
4098a896f870SMeenakshikumar Somasundaram 
4099a896f870SMeenakshikumar Somasundaram 			/* Reset all the syncd pipes from the disabled pipe */
4100a896f870SMeenakshikumar Somasundaram 			for (j = 0; j < dc->res_pool->pipe_count; j++) {
4101a896f870SMeenakshikumar Somasundaram 				pipe_ctx_syncd = &context->res_ctx.pipe_ctx[j];
4102a896f870SMeenakshikumar Somasundaram 				if ((GET_PIPE_SYNCD_FROM_PIPE(pipe_ctx_syncd) == pipe_ctx_old->pipe_idx) ||
4103a896f870SMeenakshikumar Somasundaram 					!IS_PIPE_SYNCD_VALID(pipe_ctx_syncd))
4104a896f870SMeenakshikumar Somasundaram 					SET_PIPE_SYNCD_TO_PIPE(pipe_ctx_syncd, j);
4105a896f870SMeenakshikumar Somasundaram 			}
4106a896f870SMeenakshikumar Somasundaram 		}
4107a896f870SMeenakshikumar Somasundaram 	}
4108a896f870SMeenakshikumar Somasundaram }
4109a896f870SMeenakshikumar Somasundaram 
check_syncd_pipes_for_disabled_master_pipe(struct dc * dc,struct dc_state * context,uint8_t disabled_master_pipe_idx)4110a896f870SMeenakshikumar Somasundaram void check_syncd_pipes_for_disabled_master_pipe(struct dc *dc,
4111a896f870SMeenakshikumar Somasundaram 	struct dc_state *context,
4112a896f870SMeenakshikumar Somasundaram 	uint8_t disabled_master_pipe_idx)
4113a896f870SMeenakshikumar Somasundaram {
4114a896f870SMeenakshikumar Somasundaram 	int i;
4115a896f870SMeenakshikumar Somasundaram 	struct pipe_ctx *pipe_ctx, *pipe_ctx_check;
4116a896f870SMeenakshikumar Somasundaram 
4117a896f870SMeenakshikumar Somasundaram 	pipe_ctx = &context->res_ctx.pipe_ctx[disabled_master_pipe_idx];
4118a896f870SMeenakshikumar Somasundaram 	if ((GET_PIPE_SYNCD_FROM_PIPE(pipe_ctx) != disabled_master_pipe_idx) ||
4119a896f870SMeenakshikumar Somasundaram 		!IS_PIPE_SYNCD_VALID(pipe_ctx))
4120a896f870SMeenakshikumar Somasundaram 		SET_PIPE_SYNCD_TO_PIPE(pipe_ctx, disabled_master_pipe_idx);
4121a896f870SMeenakshikumar Somasundaram 
4122a896f870SMeenakshikumar Somasundaram 	/* for the pipe disabled, check if any slave pipe exists and assert */
4123a896f870SMeenakshikumar Somasundaram 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
4124a896f870SMeenakshikumar Somasundaram 		pipe_ctx_check = &context->res_ctx.pipe_ctx[i];
4125a896f870SMeenakshikumar Somasundaram 
4126a896f870SMeenakshikumar Somasundaram 		if ((GET_PIPE_SYNCD_FROM_PIPE(pipe_ctx_check) == disabled_master_pipe_idx) &&
4127762e8febSAurabindo Pillai 		    IS_PIPE_SYNCD_VALID(pipe_ctx_check) && (i != disabled_master_pipe_idx)) {
4128762e8febSAurabindo Pillai 			struct pipe_ctx *first_pipe = pipe_ctx_check;
4129762e8febSAurabindo Pillai 
4130762e8febSAurabindo Pillai 			while (first_pipe->prev_odm_pipe)
4131762e8febSAurabindo Pillai 				first_pipe = first_pipe->prev_odm_pipe;
4132762e8febSAurabindo Pillai 			/* When ODM combine is enabled, this case is expected. If the disabled pipe
4133762e8febSAurabindo Pillai 			 * is part of the ODM tree, then we should not print an error.
4134762e8febSAurabindo Pillai 			 * */
4135762e8febSAurabindo Pillai 			if (first_pipe->pipe_idx == disabled_master_pipe_idx)
4136762e8febSAurabindo Pillai 				continue;
4137762e8febSAurabindo Pillai 
4138a896f870SMeenakshikumar Somasundaram 			DC_ERR("DC: Failure: pipe_idx[%d] syncd with disabled master pipe_idx[%d]\n",
4139a896f870SMeenakshikumar Somasundaram 				   i, disabled_master_pipe_idx);
4140a896f870SMeenakshikumar Somasundaram 		}
4141a896f870SMeenakshikumar Somasundaram 	}
4142762e8febSAurabindo Pillai }
4143580013b2SWenjing Liu 
reset_sync_context_for_pipe(const struct dc * dc,struct dc_state * context,uint8_t pipe_idx)4144abffd871SMeenakshikumar Somasundaram void reset_sync_context_for_pipe(const struct dc *dc,
4145abffd871SMeenakshikumar Somasundaram 	struct dc_state *context,
4146abffd871SMeenakshikumar Somasundaram 	uint8_t pipe_idx)
4147abffd871SMeenakshikumar Somasundaram {
4148abffd871SMeenakshikumar Somasundaram 	int i;
4149abffd871SMeenakshikumar Somasundaram 	struct pipe_ctx *pipe_ctx_reset;
4150abffd871SMeenakshikumar Somasundaram 
4151abffd871SMeenakshikumar Somasundaram 	/* reset the otg sync context for the pipe and its slave pipes if any */
4152abffd871SMeenakshikumar Somasundaram 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
4153abffd871SMeenakshikumar Somasundaram 		pipe_ctx_reset = &context->res_ctx.pipe_ctx[i];
4154abffd871SMeenakshikumar Somasundaram 
4155abffd871SMeenakshikumar Somasundaram 		if (((GET_PIPE_SYNCD_FROM_PIPE(pipe_ctx_reset) == pipe_idx) &&
4156abffd871SMeenakshikumar Somasundaram 			IS_PIPE_SYNCD_VALID(pipe_ctx_reset)) || (i == pipe_idx))
4157abffd871SMeenakshikumar Somasundaram 			SET_PIPE_SYNCD_TO_PIPE(pipe_ctx_reset, i);
4158abffd871SMeenakshikumar Somasundaram 	}
4159abffd871SMeenakshikumar Somasundaram }
4160abffd871SMeenakshikumar Somasundaram 
resource_transmitter_to_phy_idx(const struct dc * dc,enum transmitter transmitter)4161580013b2SWenjing Liu uint8_t resource_transmitter_to_phy_idx(const struct dc *dc, enum transmitter transmitter)
4162580013b2SWenjing Liu {
4163580013b2SWenjing Liu 	/* TODO - get transmitter to phy idx mapping from DMUB */
4164580013b2SWenjing Liu 	uint8_t phy_idx = transmitter - TRANSMITTER_UNIPHY_A;
4165580013b2SWenjing Liu 
4166580013b2SWenjing Liu 	if (dc->ctx->dce_version == DCN_VERSION_3_1 &&
4167580013b2SWenjing Liu 			dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
4168580013b2SWenjing Liu 		switch (transmitter) {
4169580013b2SWenjing Liu 		case TRANSMITTER_UNIPHY_A:
4170580013b2SWenjing Liu 			phy_idx = 0;
4171580013b2SWenjing Liu 			break;
4172580013b2SWenjing Liu 		case TRANSMITTER_UNIPHY_B:
4173580013b2SWenjing Liu 			phy_idx = 1;
4174580013b2SWenjing Liu 			break;
4175580013b2SWenjing Liu 		case TRANSMITTER_UNIPHY_C:
4176580013b2SWenjing Liu 			phy_idx = 5;
4177580013b2SWenjing Liu 			break;
4178580013b2SWenjing Liu 		case TRANSMITTER_UNIPHY_D:
4179580013b2SWenjing Liu 			phy_idx = 6;
4180580013b2SWenjing Liu 			break;
4181580013b2SWenjing Liu 		case TRANSMITTER_UNIPHY_E:
4182580013b2SWenjing Liu 			phy_idx = 4;
4183580013b2SWenjing Liu 			break;
4184580013b2SWenjing Liu 		default:
4185580013b2SWenjing Liu 			phy_idx = 0;
4186580013b2SWenjing Liu 			break;
4187580013b2SWenjing Liu 		}
4188580013b2SWenjing Liu 	}
418959b8ca24SAlex Hung 
4190580013b2SWenjing Liu 	return phy_idx;
4191580013b2SWenjing Liu }
41922750caffSWenjing Liu 
get_link_hwss(const struct dc_link * link,const struct link_resource * link_res)41932750caffSWenjing Liu const struct link_hwss *get_link_hwss(const struct dc_link *link,
41942750caffSWenjing Liu 		const struct link_resource *link_res)
41952750caffSWenjing Liu {
41962750caffSWenjing Liu 	/* Link_hwss is only accessible by getter function instead of accessing
41972750caffSWenjing Liu 	 * by pointers in dc with the intent to protect against breaking polymorphism.
41982750caffSWenjing Liu 	 */
41992750caffSWenjing Liu 	if (can_use_hpo_dp_link_hwss(link, link_res))
42002750caffSWenjing Liu 		/* TODO: some assumes that if decided link settings is 128b/132b
42012750caffSWenjing Liu 		 * channel coding format hpo_dp_link_enc should be used.
42022750caffSWenjing Liu 		 * Others believe that if hpo_dp_link_enc is available in link
42032750caffSWenjing Liu 		 * resource then hpo_dp_link_enc must be used. This bound between
42042750caffSWenjing Liu 		 * hpo_dp_link_enc != NULL and decided link settings is loosely coupled
42052750caffSWenjing Liu 		 * with a premise that both hpo_dp_link_enc pointer and decided link
42062750caffSWenjing Liu 		 * settings are determined based on single policy function like
42072750caffSWenjing Liu 		 * "decide_link_settings" from upper layer. This "convention"
42082750caffSWenjing Liu 		 * cannot be maintained and enforced at current level.
42092750caffSWenjing Liu 		 * Therefore a refactor is due so we can enforce a strong bound
42102750caffSWenjing Liu 		 * between those two parameters at this level.
42112750caffSWenjing Liu 		 *
42122750caffSWenjing Liu 		 * To put it simple, we want to make enforcement at low level so that
42132750caffSWenjing Liu 		 * we will not return link hwss if caller plans to do 8b/10b
42142750caffSWenjing Liu 		 * with an hpo encoder. Or we can return a very dummy one that doesn't
42152750caffSWenjing Liu 		 * do work for all functions
42162750caffSWenjing Liu 		 */
4217ad5594adSMichael Strauss 		return (requires_fixed_vs_pe_retimer_hpo_link_hwss(link) ?
4218ad5594adSMichael Strauss 				get_hpo_fixed_vs_pe_retimer_dp_link_hwss() : get_hpo_dp_link_hwss());
42192750caffSWenjing Liu 	else if (can_use_dpia_link_hwss(link, link_res))
42202750caffSWenjing Liu 		return get_dpia_link_hwss();
42212750caffSWenjing Liu 	else if (can_use_dio_link_hwss(link, link_res))
4222ad5594adSMichael Strauss 		return (requires_fixed_vs_pe_retimer_dio_link_hwss(link)) ?
4223ad5594adSMichael Strauss 				get_dio_fixed_vs_pe_retimer_link_hwss() : get_dio_link_hwss();
42242750caffSWenjing Liu 	else
42252750caffSWenjing Liu 		return get_virtual_link_hwss();
42262750caffSWenjing Liu }
42276349c738SAlvin Lee 
is_h_timing_divisible_by_2(struct dc_stream_state * stream)42286349c738SAlvin Lee bool is_h_timing_divisible_by_2(struct dc_stream_state *stream)
42296349c738SAlvin Lee {
42306349c738SAlvin Lee 	bool divisible = false;
42316349c738SAlvin Lee 	uint16_t h_blank_start = 0;
42326349c738SAlvin Lee 	uint16_t h_blank_end = 0;
42336349c738SAlvin Lee 
42346349c738SAlvin Lee 	if (stream) {
42356349c738SAlvin Lee 		h_blank_start = stream->timing.h_total - stream->timing.h_front_porch;
42366349c738SAlvin Lee 		h_blank_end = h_blank_start - stream->timing.h_addressable;
42376349c738SAlvin Lee 
42386349c738SAlvin Lee 		/* HTOTAL, Hblank start/end, and Hsync start/end all must be
42396349c738SAlvin Lee 		 * divisible by 2 in order for the horizontal timing params
42406349c738SAlvin Lee 		 * to be considered divisible by 2. Hsync start is always 0.
42416349c738SAlvin Lee 		 */
42426349c738SAlvin Lee 		divisible = (stream->timing.h_total % 2 == 0) &&
42436349c738SAlvin Lee 				(h_blank_start % 2 == 0) &&
42446349c738SAlvin Lee 				(h_blank_end % 2 == 0) &&
42456349c738SAlvin Lee 				(stream->timing.h_sync_width % 2 == 0);
42466349c738SAlvin Lee 	}
42476349c738SAlvin Lee 	return divisible;
42486349c738SAlvin Lee }
424920dad381SJun Lei 
dc_resource_acquire_secondary_pipe_for_mpc_odm(const struct dc * dc,struct dc_state * state,struct pipe_ctx * pri_pipe,struct pipe_ctx * sec_pipe,bool odm)425020dad381SJun Lei bool dc_resource_acquire_secondary_pipe_for_mpc_odm(
425120dad381SJun Lei 		const struct dc *dc,
425220dad381SJun Lei 		struct dc_state *state,
425320dad381SJun Lei 		struct pipe_ctx *pri_pipe,
425420dad381SJun Lei 		struct pipe_ctx *sec_pipe,
425520dad381SJun Lei 		bool odm)
425620dad381SJun Lei {
425720dad381SJun Lei 	int pipe_idx = sec_pipe->pipe_idx;
425820dad381SJun Lei 	struct pipe_ctx *sec_top, *sec_bottom, *sec_next, *sec_prev;
425920dad381SJun Lei 	const struct resource_pool *pool = dc->res_pool;
426020dad381SJun Lei 
426120dad381SJun Lei 	sec_top = sec_pipe->top_pipe;
426220dad381SJun Lei 	sec_bottom = sec_pipe->bottom_pipe;
426320dad381SJun Lei 	sec_next = sec_pipe->next_odm_pipe;
426420dad381SJun Lei 	sec_prev = sec_pipe->prev_odm_pipe;
426520dad381SJun Lei 
426620dad381SJun Lei 	*sec_pipe = *pri_pipe;
426720dad381SJun Lei 
426820dad381SJun Lei 	sec_pipe->top_pipe = sec_top;
426920dad381SJun Lei 	sec_pipe->bottom_pipe = sec_bottom;
427020dad381SJun Lei 	sec_pipe->next_odm_pipe = sec_next;
427120dad381SJun Lei 	sec_pipe->prev_odm_pipe = sec_prev;
427220dad381SJun Lei 
427320dad381SJun Lei 	sec_pipe->pipe_idx = pipe_idx;
427420dad381SJun Lei 	sec_pipe->plane_res.mi = pool->mis[pipe_idx];
427520dad381SJun Lei 	sec_pipe->plane_res.hubp = pool->hubps[pipe_idx];
427620dad381SJun Lei 	sec_pipe->plane_res.ipp = pool->ipps[pipe_idx];
427720dad381SJun Lei 	sec_pipe->plane_res.xfm = pool->transforms[pipe_idx];
427820dad381SJun Lei 	sec_pipe->plane_res.dpp = pool->dpps[pipe_idx];
427920dad381SJun Lei 	sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst;
428020dad381SJun Lei 	sec_pipe->stream_res.dsc = NULL;
428120dad381SJun Lei 	if (odm) {
428220dad381SJun Lei 		if (!sec_pipe->top_pipe)
428320dad381SJun Lei 			sec_pipe->stream_res.opp = pool->opps[pipe_idx];
428420dad381SJun Lei 		else
428520dad381SJun Lei 			sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp;
428620dad381SJun Lei 		if (sec_pipe->stream->timing.flags.DSC == 1) {
42874652ae7aSHarry Wentland #if defined(CONFIG_DRM_AMD_DC_FP)
428820dad381SJun Lei 			dcn20_acquire_dsc(dc, &state->res_ctx, &sec_pipe->stream_res.dsc, pipe_idx);
4289eff4ccd1SYang Yingliang #endif
429020dad381SJun Lei 			ASSERT(sec_pipe->stream_res.dsc);
429120dad381SJun Lei 			if (sec_pipe->stream_res.dsc == NULL)
429220dad381SJun Lei 				return false;
429320dad381SJun Lei 		}
42944652ae7aSHarry Wentland #if defined(CONFIG_DRM_AMD_DC_FP)
429520dad381SJun Lei 		dcn20_build_mapped_resource(dc, state, sec_pipe->stream);
4296eff4ccd1SYang Yingliang #endif
429720dad381SJun Lei 	}
429820dad381SJun Lei 
429920dad381SJun Lei 	return true;
430020dad381SJun Lei }
43010e8cf83aSWenjing Liu 
update_dp_encoder_resources_for_test_harness(const struct dc * dc,struct dc_state * context,struct pipe_ctx * pipe_ctx)43020e8cf83aSWenjing Liu enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
43030e8cf83aSWenjing Liu 		struct dc_state *context,
43040e8cf83aSWenjing Liu 		struct pipe_ctx *pipe_ctx)
43050e8cf83aSWenjing Liu {
430698ce7d32SWenjing Liu 	if (dc->link_srv->dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) {
43070e8cf83aSWenjing Liu 		if (pipe_ctx->stream_res.hpo_dp_stream_enc == NULL) {
43080e8cf83aSWenjing Liu 			pipe_ctx->stream_res.hpo_dp_stream_enc =
43090e8cf83aSWenjing Liu 					find_first_free_match_hpo_dp_stream_enc_for_link(
43100e8cf83aSWenjing Liu 							&context->res_ctx, dc->res_pool, pipe_ctx->stream);
43110e8cf83aSWenjing Liu 
43120e8cf83aSWenjing Liu 			if (!pipe_ctx->stream_res.hpo_dp_stream_enc)
43130e8cf83aSWenjing Liu 				return DC_NO_STREAM_ENC_RESOURCE;
43140e8cf83aSWenjing Liu 
43150e8cf83aSWenjing Liu 			update_hpo_dp_stream_engine_usage(
43160e8cf83aSWenjing Liu 					&context->res_ctx, dc->res_pool,
43170e8cf83aSWenjing Liu 					pipe_ctx->stream_res.hpo_dp_stream_enc,
43180e8cf83aSWenjing Liu 					true);
43190e8cf83aSWenjing Liu 		}
43200e8cf83aSWenjing Liu 
43210e8cf83aSWenjing Liu 		if (pipe_ctx->link_res.hpo_dp_link_enc == NULL) {
43220e8cf83aSWenjing Liu 			if (!add_hpo_dp_link_enc_to_ctx(&context->res_ctx, dc->res_pool, pipe_ctx, pipe_ctx->stream))
43230e8cf83aSWenjing Liu 				return DC_NO_LINK_ENC_RESOURCE;
43240e8cf83aSWenjing Liu 		}
43250e8cf83aSWenjing Liu 	} else {
43260e8cf83aSWenjing Liu 		if (pipe_ctx->stream_res.hpo_dp_stream_enc) {
43270e8cf83aSWenjing Liu 			update_hpo_dp_stream_engine_usage(
43280e8cf83aSWenjing Liu 					&context->res_ctx, dc->res_pool,
43290e8cf83aSWenjing Liu 					pipe_ctx->stream_res.hpo_dp_stream_enc,
43300e8cf83aSWenjing Liu 					false);
43310e8cf83aSWenjing Liu 			pipe_ctx->stream_res.hpo_dp_stream_enc = NULL;
43320e8cf83aSWenjing Liu 		}
43330e8cf83aSWenjing Liu 		if (pipe_ctx->link_res.hpo_dp_link_enc)
43340e8cf83aSWenjing Liu 			remove_hpo_dp_link_enc_from_ctx(&context->res_ctx, pipe_ctx, pipe_ctx->stream);
43350e8cf83aSWenjing Liu 	}
43360e8cf83aSWenjing Liu 
43370e8cf83aSWenjing Liu 	return DC_OK;
43380e8cf83aSWenjing Liu }
43390e8cf83aSWenjing Liu 
4340