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